/*!
 * (The MIT License)
 * 
 * Copyright (c) 2012-2014 Marcin Warpechowski
 * Copyright (c) 2015 Handsoncode sp. z o.o. <hello@handsoncode.net>
 * 
 * Permission is hereby granted, free of charge, to any person obtaining
 * a copy of this software and associated documentation files (the
 * 'Software'), to deal in the Software without restriction, including
 * without limitation the rights to use, copy, modify, merge, publish,
 * distribute, sublicense, and/or sell copies of the Software, and to
 * permit persons to whom the Software is furnished to do so, subject to
 * the following conditions:
 * 
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 * 
 * Version: 0.34.1
 * Date: Thu Sep 07 2017 15:34:10 GMT+0200 (CEST)
 */
(function webpackUniversalModuleDefinition(root, factory) {
	if(typeof exports === 'object' && typeof module === 'object')
		module.exports = factory();
	else if(typeof define === 'function' && define.amd)
		define("Handsontable", [], factory);
	else if(typeof exports === 'object')
		exports["Handsontable"] = factory();
	else
		root["Handsontable"] = factory();
})(this, function() {
return /******/ (function(modules) { // webpackBootstrap
/******/ 	// The module cache
/******/ 	var installedModules = {};
/******/
/******/ 	// The require function
/******/ 	function __webpack_require__(moduleId) {
/******/
/******/ 		// Check if module is in cache
/******/ 		if(installedModules[moduleId]) {
/******/ 			return installedModules[moduleId].exports;
/******/ 		}
/******/ 		// Create a new module (and put it into the cache)
/******/ 		var module = installedModules[moduleId] = {
/******/ 			i: moduleId,
/******/ 			l: false,
/******/ 			exports: {}
/******/ 		};
/******/
/******/ 		// Execute the module function
/******/ 		modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
/******/
/******/ 		// Flag the module as loaded
/******/ 		module.l = true;
/******/
/******/ 		// Return the exports of the module
/******/ 		return module.exports;
/******/ 	}
/******/
/******/
/******/ 	// expose the modules object (__webpack_modules__)
/******/ 	__webpack_require__.m = modules;
/******/
/******/ 	// expose the module cache
/******/ 	__webpack_require__.c = installedModules;
/******/
/******/ 	// identity function for calling harmony imports with the correct context
/******/ 	__webpack_require__.i = function(value) { return value; };
/******/
/******/ 	// define getter function for harmony exports
/******/ 	__webpack_require__.d = function(exports, name, getter) {
/******/ 		if(!__webpack_require__.o(exports, name)) {
/******/ 			Object.defineProperty(exports, name, {
/******/ 				configurable: false,
/******/ 				enumerable: true,
/******/ 				get: getter
/******/ 			});
/******/ 		}
/******/ 	};
/******/
/******/ 	// getDefaultExport function for compatibility with non-harmony modules
/******/ 	__webpack_require__.n = function(module) {
/******/ 		var getter = module && module.__esModule ?
/******/ 			function getDefault() { return module['default']; } :
/******/ 			function getModuleExports() { return module; };
/******/ 		__webpack_require__.d(getter, 'a', getter);
/******/ 		return getter;
/******/ 	};
/******/
/******/ 	// Object.prototype.hasOwnProperty.call
/******/ 	__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
/******/
/******/ 	// __webpack_public_path__
/******/ 	__webpack_require__.p = "";
/******/
/******/ 	// Load entry module and return exports
/******/ 	return __webpack_require__(__webpack_require__.s = 332);
/******/ })
/************************************************************************/
/******/ ([
/* 0 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


exports.__esModule = true;
exports.HTML_CHARACTERS = undefined;
exports.getParent = getParent;
exports.closest = closest;
exports.closestDown = closestDown;
exports.isChildOf = isChildOf;
exports.isChildOfWebComponentTable = isChildOfWebComponentTable;
exports.polymerWrap = polymerWrap;
exports.polymerUnwrap = polymerUnwrap;
exports.index = index;
exports.overlayContainsElement = overlayContainsElement;
exports.hasClass = hasClass;
exports.addClass = addClass;
exports.removeClass = removeClass;
exports.removeTextNodes = removeTextNodes;
exports.empty = empty;
exports.fastInnerHTML = fastInnerHTML;
exports.fastInnerText = fastInnerText;
exports.isVisible = isVisible;
exports.offset = offset;
exports.getWindowScrollTop = getWindowScrollTop;
exports.getWindowScrollLeft = getWindowScrollLeft;
exports.getScrollTop = getScrollTop;
exports.getScrollLeft = getScrollLeft;
exports.getScrollableElement = getScrollableElement;
exports.getTrimmingContainer = getTrimmingContainer;
exports.getStyle = getStyle;
exports.getComputedStyle = getComputedStyle;
exports.outerWidth = outerWidth;
exports.outerHeight = outerHeight;
exports.innerHeight = innerHeight;
exports.innerWidth = innerWidth;
exports.addEvent = addEvent;
exports.removeEvent = removeEvent;
exports.getCaretPosition = getCaretPosition;
exports.getSelectionEndPosition = getSelectionEndPosition;
exports.getSelectionText = getSelectionText;
exports.setCaretPosition = setCaretPosition;
exports.getScrollbarWidth = getScrollbarWidth;
exports.hasVerticalScrollbar = hasVerticalScrollbar;
exports.hasHorizontalScrollbar = hasHorizontalScrollbar;
exports.setOverlayPosition = setOverlayPosition;
exports.getCssTransform = getCssTransform;
exports.resetCssTransform = resetCssTransform;
exports.isInput = isInput;
exports.isOutsideInput = isOutsideInput;

var _browser = __webpack_require__(22);

var _feature = __webpack_require__(34);

/**
 * Get the parent of the specified node in the DOM tree.
 *
 * @param  {HTMLElement} element Element from which traversing is started.
 * @param  {Number} [level=0] Traversing deep level.
 * @return {HTMLElement|null}
 */
function getParent(element) {
  var level = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;

  var iteration = -1;
  var parent = null;

  while (element != null) {
    if (iteration === level) {
      parent = element;
      break;
    }

    if (element.host && element.nodeType === Node.DOCUMENT_FRAGMENT_NODE) {
      element = element.host;
    } else {
      iteration++;
      element = element.parentNode;
    }
  }

  return parent;
}

/**
 * Goes up the DOM tree (including given element) until it finds an element that matches the nodes or nodes name.
 * This method goes up through web components.
 *
 * @param {HTMLElement} element Element from which traversing is started
 * @param {Array} nodes Array of elements or Array of elements name
 * @param {HTMLElement} [until]
 * @returns {HTMLElement|null}
 */
function closest(element, nodes, until) {
  while (element != null && element !== until) {
    if (element.nodeType === Node.ELEMENT_NODE && (nodes.indexOf(element.nodeName) > -1 || nodes.indexOf(element) > -1)) {
      return element;
    }
    if (element.host && element.nodeType === Node.DOCUMENT_FRAGMENT_NODE) {
      element = element.host;
    } else {
      element = element.parentNode;
    }
  }

  return null;
}

/**
 * Goes "down" the DOM tree (including given element) until it finds an element that matches the nodes or nodes name.
 *
 * @param {HTMLElement} element Element from which traversing is started
 * @param {Array} nodes Array of elements or Array of elements name
 * @param {HTMLElement} [until]
 * @returns {HTMLElement|null}
 */
function closestDown(element, nodes, until) {
  var matched = [];

  while (element) {
    element = closest(element, nodes, until);

    if (!element || until && !until.contains(element)) {
      break;
    }
    matched.push(element);

    if (element.host && element.nodeType === Node.DOCUMENT_FRAGMENT_NODE) {
      element = element.host;
    } else {
      element = element.parentNode;
    }
  }
  var length = matched.length;

  return length ? matched[length - 1] : null;
}

/**
 * Goes up the DOM tree and checks if element is child of another element.
 *
 * @param child Child element
 * @param {Object|String} parent Parent element OR selector of the parent element.
 *                               If string provided, function returns `true` for the first occurrence of element with that class.
 * @returns {Boolean}
 */
function isChildOf(child, parent) {
  var node = child.parentNode;
  var queriedParents = [];

  if (typeof parent === 'string') {
    queriedParents = Array.prototype.slice.call(document.querySelectorAll(parent), 0);
  } else {
    queriedParents.push(parent);
  }

  while (node != null) {
    if (queriedParents.indexOf(node) > -1) {
      return true;
    }
    node = node.parentNode;
  }

  return false;
}

/**
 * Check if an element is part of `hot-table` web component.
 *
 * @param {Element} element
 * @returns {Boolean}
 */
function isChildOfWebComponentTable(element) {
  var hotTableName = 'hot-table',
      result = false,
      parentNode;

  parentNode = polymerWrap(element);

  function isHotTable(element) {
    return element.nodeType === Node.ELEMENT_NODE && element.nodeName === hotTableName.toUpperCase();
  }

  while (parentNode != null) {
    if (isHotTable(parentNode)) {
      result = true;
      break;
    } else if (parentNode.host && parentNode.nodeType === Node.DOCUMENT_FRAGMENT_NODE) {
      result = isHotTable(parentNode.host);

      if (result) {
        break;
      }
      parentNode = parentNode.host;
    }
    parentNode = parentNode.parentNode;
  }

  return result;
}

/**
 * Wrap element into polymer/webcomponent container if exists
 *
 * @param element
 * @returns {*}
 */
function polymerWrap(element) {
  /* global Polymer */
  return typeof Polymer !== 'undefined' && typeof wrap === 'function' ? wrap(element) : element;
}

/**
 * Unwrap element from polymer/webcomponent container if exists
 *
 * @param element
 * @returns {*}
 */
function polymerUnwrap(element) {
  /* global Polymer */
  return typeof Polymer !== 'undefined' && typeof unwrap === 'function' ? unwrap(element) : element;
}

/**
 * Counts index of element within its parent
 * WARNING: for performance reasons, assumes there are only element nodes (no text nodes). This is true for Walkotnable
 * Otherwise would need to check for nodeType or use previousElementSibling
 *
 * @see http://jsperf.com/sibling-index/10
 * @param {Element} element
 * @return {Number}
 */
function index(element) {
  var i = 0;

  if (element.previousSibling) {
    /* eslint-disable no-cond-assign */
    while (element = element.previousSibling) {
      ++i;
    }
  }

  return i;
}

/**
 * Check if the provided overlay contains the provided element
 *
 * @param {String} overlay
 * @param {HTMLElement} element
 * @returns {boolean}
 */
function overlayContainsElement(overlayType, element) {
  var overlayElement = document.querySelector('.ht_clone_' + overlayType);
  return overlayElement ? overlayElement.contains(element) : null;
}

var classListSupport = !!document.documentElement.classList;
var _hasClass, _addClass, _removeClass;

function filterEmptyClassNames(classNames) {
  var len = 0,
      result = [];

  if (!classNames || !classNames.length) {
    return result;
  }
  while (classNames[len]) {
    result.push(classNames[len]);
    len++;
  }

  return result;
}

if (classListSupport) {
  var isSupportMultipleClassesArg = function () {
    var element = document.createElement('div');

    element.classList.add('test', 'test2');

    return element.classList.contains('test2');
  }();

  _hasClass = function _hasClass(element, className) {
    if (element.classList === void 0 || className === '') {
      return false;
    }

    return element.classList.contains(className);
  };

  _addClass = function _addClass(element, className) {
    var len = 0;

    if (typeof className === 'string') {
      className = className.split(' ');
    }
    className = filterEmptyClassNames(className);

    if (isSupportMultipleClassesArg) {
      element.classList.add.apply(element.classList, className);
    } else {
      while (className && className[len]) {
        element.classList.add(className[len]);
        len++;
      }
    }
  };

  _removeClass = function _removeClass(element, className) {
    var len = 0;

    if (typeof className === 'string') {
      className = className.split(' ');
    }
    className = filterEmptyClassNames(className);

    if (isSupportMultipleClassesArg) {
      element.classList.remove.apply(element.classList, className);
    } else {
      while (className && className[len]) {
        element.classList.remove(className[len]);
        len++;
      }
    }
  };
} else {
  var createClassNameRegExp = function createClassNameRegExp(className) {
    return new RegExp('(\\s|^)' + className + '(\\s|$)');
  };

  _hasClass = function _hasClass(element, className) {
    // http://snipplr.com/view/3561/addclass-removeclass-hasclass/
    return element.className !== void 0 && element.className.test(createClassNameRegExp(className));
  };

  _addClass = function _addClass(element, className) {
    var len = 0,
        _className = element.className;

    if (typeof className === 'string') {
      className = className.split(' ');
    }
    if (_className === '') {
      _className = className.join(' ');
    } else {
      while (className && className[len]) {
        if (!createClassNameRegExp(className[len]).test(_className)) {
          _className += ' ' + className[len];
        }
        len++;
      }
    }
    element.className = _className;
  };

  _removeClass = function _removeClass(element, className) {
    var len = 0,
        _className = element.className;

    if (typeof className === 'string') {
      className = className.split(' ');
    }
    while (className && className[len]) {
      // String.prototype.trim is defined in polyfill.js
      _className = _className.replace(createClassNameRegExp(className[len]), ' ').trim();
      len++;
    }
    if (element.className !== _className) {
      element.className = _className;
    }
  };
}

/**
 * Checks if element has class name
 *
 * @param {HTMLElement} element
 * @param {String} className Class name to check
 * @returns {Boolean}
 */
function hasClass(element, className) {
  return _hasClass(element, className);
}

/**
 * Add class name to an element
 *
 * @param {HTMLElement} element
 * @param {String|Array} className Class name as string or array of strings
 */
function addClass(element, className) {
  return _addClass(element, className);
}

/**
 * Remove class name from an element
 *
 * @param {HTMLElement} element
 * @param {String|Array} className Class name as string or array of strings
 */
function removeClass(element, className) {
  return _removeClass(element, className);
}

function removeTextNodes(element, parent) {
  if (element.nodeType === 3) {
    parent.removeChild(element); // bye text nodes!
  } else if (['TABLE', 'THEAD', 'TBODY', 'TFOOT', 'TR'].indexOf(element.nodeName) > -1) {
    var childs = element.childNodes;
    for (var i = childs.length - 1; i >= 0; i--) {
      removeTextNodes(childs[i], element);
    }
  }
}

/**
 * Remove childs function
 * WARNING - this doesn't unload events and data attached by jQuery
 * http://jsperf.com/jquery-html-vs-empty-vs-innerhtml/9
 * http://jsperf.com/jquery-html-vs-empty-vs-innerhtml/11 - no siginificant improvement with Chrome remove() method
 *
 * @param element
 * @returns {void}
 */
//
function empty(element) {
  var child;
  /* eslint-disable no-cond-assign */
  while (child = element.lastChild) {
    element.removeChild(child);
  }
}

var HTML_CHARACTERS = exports.HTML_CHARACTERS = /(<(.*)>|&(.*);)/;

/**
 * Insert content into element trying avoid innerHTML method.
 * @return {void}
 */
function fastInnerHTML(element, content) {
  if (HTML_CHARACTERS.test(content)) {
    element.innerHTML = content;
  } else {
    fastInnerText(element, content);
  }
}

/**
 * Insert text content into element
 * @return {void}
 */

var textContextSupport = !!document.createTextNode('test').textContent;

function fastInnerText(element, content) {
  var child = element.firstChild;

  if (child && child.nodeType === 3 && child.nextSibling === null) {
    // fast lane - replace existing text node

    if (textContextSupport) {
      // http://jsperf.com/replace-text-vs-reuse
      child.textContent = content;
    } else {
      // http://jsperf.com/replace-text-vs-reuse
      child.data = content;
    }
  } else {
    // slow lane - empty element and insert a text node
    empty(element);
    element.appendChild(document.createTextNode(content));
  }
}

/**
 * Returns true if element is attached to the DOM and visible, false otherwise
 * @param elem
 * @returns {boolean}
 */
function isVisible(elem) {
  var next = elem;

  while (polymerUnwrap(next) !== document.documentElement) {
    // until <html> reached
    if (next === null) {
      // parent detached from DOM
      return false;
    } else if (next.nodeType === Node.DOCUMENT_FRAGMENT_NODE) {
      if (next.host) {
        // this is Web Components Shadow DOM
        // see: http://w3c.github.io/webcomponents/spec/shadow/#encapsulation
        // according to spec, should be if (next.ownerDocument !== window.document), but that doesn't work yet
        if (next.host.impl) {
          // Chrome 33.0.1723.0 canary (2013-11-29) Web Platform features disabled
          return isVisible(next.host.impl);
        } else if (next.host) {
          // Chrome 33.0.1723.0 canary (2013-11-29) Web Platform features enabled
          return isVisible(next.host);
        }
        throw new Error('Lost in Web Components world');
      } else {
        return false; // this is a node detached from document in IE8
      }
    } else if (next.style.display === 'none') {
      return false;
    }
    next = next.parentNode;
  }

  return true;
}

/**
 * Returns elements top and left offset relative to the document. Function is not compatible with jQuery offset.
 *
 * @param {HTMLElement} elem
 * @return {Object} Returns object with `top` and `left` props
 */
function offset(elem) {
  var offsetLeft, offsetTop, lastElem, docElem, box;

  docElem = document.documentElement;

  if ((0, _feature.hasCaptionProblem)() && elem.firstChild && elem.firstChild.nodeName === 'CAPTION') {
    // fixes problem with Firefox ignoring <caption> in TABLE offset (see also export outerHeight)
    // http://jsperf.com/offset-vs-getboundingclientrect/8
    box = elem.getBoundingClientRect();

    return {
      top: box.top + (window.pageYOffset || docElem.scrollTop) - (docElem.clientTop || 0),
      left: box.left + (window.pageXOffset || docElem.scrollLeft) - (docElem.clientLeft || 0)
    };
  }
  offsetLeft = elem.offsetLeft;
  offsetTop = elem.offsetTop;
  lastElem = elem;

  /* eslint-disable no-cond-assign */
  while (elem = elem.offsetParent) {
    // from my observation, document.body always has scrollLeft/scrollTop == 0
    if (elem === document.body) {
      break;
    }
    offsetLeft += elem.offsetLeft;
    offsetTop += elem.offsetTop;
    lastElem = elem;
  }

  // slow - http://jsperf.com/offset-vs-getboundingclientrect/6
  if (lastElem && lastElem.style.position === 'fixed') {
    // if(lastElem !== document.body) { //faster but does gives false positive in Firefox
    offsetLeft += window.pageXOffset || docElem.scrollLeft;
    offsetTop += window.pageYOffset || docElem.scrollTop;
  }

  return {
    left: offsetLeft,
    top: offsetTop
  };
}

/**
 * Returns the document's scrollTop property.
 *
 * @returns {Number}
 */
function getWindowScrollTop() {
  var res = window.scrollY;

  if (res === void 0) {
    // IE8-11
    res = document.documentElement.scrollTop;
  }

  return res;
}

/**
 * Returns the document's scrollLeft property.
 *
 * @returns {Number}
 */
function getWindowScrollLeft() {
  var res = window.scrollX;

  if (res === void 0) {
    // IE8-11
    res = document.documentElement.scrollLeft;
  }

  return res;
}

/**
 * Returns the provided element's scrollTop property.
 *
 * @param element
 * @returns {Number}
 */
function getScrollTop(element) {
  if (element === window) {
    return getWindowScrollTop();
  }
  return element.scrollTop;
}

/**
 * Returns the provided element's scrollLeft property.
 *
 * @param element
 * @returns {Number}
 */
function getScrollLeft(element) {
  if (element === window) {
    return getWindowScrollLeft();
  }
  return element.scrollLeft;
}

/**
 * Returns a DOM element responsible for scrolling of the provided element.
 *
 * @param {HTMLElement} element
 * @returns {HTMLElement} Element's scrollable parent
 */
function getScrollableElement(element) {
  var el = element.parentNode,
      props = ['auto', 'scroll'],
      overflow,
      overflowX,
      overflowY,
      computedStyle = '',
      computedOverflow = '',
      computedOverflowY = '',
      computedOverflowX = '';

  while (el && el.style && document.body !== el) {
    overflow = el.style.overflow;
    overflowX = el.style.overflowX;
    overflowY = el.style.overflowY;

    if (overflow == 'scroll' || overflowX == 'scroll' || overflowY == 'scroll') {
      return el;
    } else if (window.getComputedStyle) {
      computedStyle = window.getComputedStyle(el);
      computedOverflow = computedStyle.getPropertyValue('overflow');
      computedOverflowY = computedStyle.getPropertyValue('overflow-y');
      computedOverflowX = computedStyle.getPropertyValue('overflow-x');

      if (computedOverflow === 'scroll' || computedOverflowX === 'scroll' || computedOverflowY === 'scroll') {
        return el;
      }
    }

    if (el.clientHeight <= el.scrollHeight && (props.indexOf(overflowY) !== -1 || props.indexOf(overflow) !== -1 || props.indexOf(computedOverflow) !== -1 || props.indexOf(computedOverflowY) !== -1)) {
      return el;
    }
    if (el.clientWidth <= el.scrollWidth && (props.indexOf(overflowX) !== -1 || props.indexOf(overflow) !== -1 || props.indexOf(computedOverflow) !== -1 || props.indexOf(computedOverflowX) !== -1)) {
      return el;
    }
    el = el.parentNode;
  }

  return window;
}

/**
 * Returns a DOM element responsible for trimming the provided element.
 *
 * @param {HTMLElement} base Base element
 * @returns {HTMLElement} Base element's trimming parent
 */
function getTrimmingContainer(base) {
  var el = base.parentNode;

  while (el && el.style && document.body !== el) {
    if (el.style.overflow !== 'visible' && el.style.overflow !== '') {
      return el;
    } else if (window.getComputedStyle) {
      var computedStyle = window.getComputedStyle(el);

      if (computedStyle.getPropertyValue('overflow') !== 'visible' && computedStyle.getPropertyValue('overflow') !== '') {
        return el;
      }
    }

    el = el.parentNode;
  }

  return window;
}

/**
 * Returns a style property for the provided element. (Be it an inline or external style).
 *
 * @param {HTMLElement} element
 * @param {String} prop Wanted property
 * @returns {String|undefined} Element's style property
 */
function getStyle(element, prop) {
  /* eslint-disable */
  if (!element) {
    return;
  } else if (element === window) {
    if (prop === 'width') {
      return window.innerWidth + 'px';
    } else if (prop === 'height') {
      return window.innerHeight + 'px';
    }

    return;
  }

  var styleProp = element.style[prop],
      computedStyle;

  if (styleProp !== '' && styleProp !== void 0) {
    return styleProp;
  } else {
    computedStyle = getComputedStyle(element);

    if (computedStyle[prop] !== '' && computedStyle[prop] !== void 0) {
      return computedStyle[prop];
    }
  }
}

/**
 * Returns a computed style object for the provided element. (Needed if style is declared in external stylesheet).
 *
 * @param element
 * @returns {IEElementStyle|CssStyle} Elements computed style object
 */
function getComputedStyle(element) {
  return element.currentStyle || document.defaultView.getComputedStyle(element);
}

/**
 * Returns the element's outer width.
 *
 * @param element
 * @returns {number} Element's outer width
 */
function outerWidth(element) {
  return element.offsetWidth;
}

/**
 * Returns the element's outer height
 *
 * @param elem
 * @returns {number} Element's outer height
 */
function outerHeight(elem) {
  if ((0, _feature.hasCaptionProblem)() && elem.firstChild && elem.firstChild.nodeName === 'CAPTION') {
    // fixes problem with Firefox ignoring <caption> in TABLE.offsetHeight
    // jQuery (1.10.1) still has this unsolved
    // may be better to just switch to getBoundingClientRect
    // http://bililite.com/blog/2009/03/27/finding-the-size-of-a-table/
    // http://lists.w3.org/Archives/Public/www-style/2009Oct/0089.html
    // http://bugs.jquery.com/ticket/2196
    // http://lists.w3.org/Archives/Public/www-style/2009Oct/0140.html#start140
    return elem.offsetHeight + elem.firstChild.offsetHeight;
  }

  return elem.offsetHeight;
}

/**
 * Returns the element's inner height.
 *
 * @param element
 * @returns {number} Element's inner height
 */
function innerHeight(element) {
  return element.clientHeight || element.innerHeight;
}

/**
 * Returns the element's inner width.
 *
 * @param element
 * @returns {number} Element's inner width
 */
function innerWidth(element) {
  return element.clientWidth || element.innerWidth;
}

function addEvent(element, event, callback) {
  if (window.addEventListener) {
    element.addEventListener(event, callback, false);
  } else {
    element.attachEvent('on' + event, callback);
  }
}

function removeEvent(element, event, callback) {
  if (window.removeEventListener) {
    element.removeEventListener(event, callback, false);
  } else {
    element.detachEvent('on' + event, callback);
  }
}

/**
 * Returns caret position in text input
 *
 * @author http://stackoverflow.com/questions/263743/how-to-get-caret-position-in-textarea
 * @return {Number}
 */
function getCaretPosition(el) {
  if (el.selectionStart) {
    return el.selectionStart;
  } else if (document.selection) {
    // IE8
    el.focus();

    var r = document.selection.createRange();

    if (r == null) {
      return 0;
    }
    var re = el.createTextRange();
    var rc = re.duplicate();

    re.moveToBookmark(r.getBookmark());
    rc.setEndPoint('EndToStart', re);

    return rc.text.length;
  }

  return 0;
}

/**
 * Returns end of the selection in text input
 *
 * @return {Number}
 */
function getSelectionEndPosition(el) {
  if (el.selectionEnd) {
    return el.selectionEnd;
  } else if (document.selection) {
    // IE8
    var r = document.selection.createRange();

    if (r == null) {
      return 0;
    }
    var re = el.createTextRange();

    return re.text.indexOf(r.text) + r.text.length;
  }

  return 0;
}

/**
 * Returns text under selection.
 *
 * @returns {String}
 */
function getSelectionText() {
  var text = '';

  if (window.getSelection) {
    text = window.getSelection().toString();
  } else if (document.selection && document.selection.type !== 'Control') {
    text = document.selection.createRange().text;
  }

  return text;
}

/**
 * Sets caret position in text input.
 *
 * @author http://blog.vishalon.net/index.php/javascript-getting-and-setting-caret-position-in-textarea/
 * @param {Element} element
 * @param {Number} pos
 * @param {Number} endPos
 */
function setCaretPosition(element, pos, endPos) {
  if (endPos === void 0) {
    endPos = pos;
  }
  if (element.setSelectionRange) {
    element.focus();

    try {
      element.setSelectionRange(pos, endPos);
    } catch (err) {
      var elementParent = element.parentNode;
      var parentDisplayValue = elementParent.style.display;
      elementParent.style.display = 'block';
      element.setSelectionRange(pos, endPos);
      elementParent.style.display = parentDisplayValue;
    }
  } else if (element.createTextRange) {
    // IE8
    var range = element.createTextRange();
    range.collapse(true);
    range.moveEnd('character', endPos);
    range.moveStart('character', pos);
    range.select();
  }
}

var cachedScrollbarWidth;

// http://stackoverflow.com/questions/986937/how-can-i-get-the-browsers-scrollbar-sizes
function walkontableCalculateScrollbarWidth() {
  var inner = document.createElement('div');
  inner.style.height = '200px';
  inner.style.width = '100%';

  var outer = document.createElement('div');
  outer.style.boxSizing = 'content-box';
  outer.style.height = '150px';
  outer.style.left = '0px';
  outer.style.overflow = 'hidden';
  outer.style.position = 'absolute';
  outer.style.top = '0px';
  outer.style.width = '200px';
  outer.style.visibility = 'hidden';
  outer.appendChild(inner);

  (document.body || document.documentElement).appendChild(outer);
  var w1 = inner.offsetWidth;
  outer.style.overflow = 'scroll';
  var w2 = inner.offsetWidth;
  if (w1 == w2) {
    w2 = outer.clientWidth;
  }

  (document.body || document.documentElement).removeChild(outer);

  return w1 - w2;
}

/**
 * Returns the computed width of the native browser scroll bar.
 *
 * @return {Number} width
 */
function getScrollbarWidth() {
  if (cachedScrollbarWidth === void 0) {
    cachedScrollbarWidth = walkontableCalculateScrollbarWidth();
  }

  return cachedScrollbarWidth;
}

/**
 * Checks if the provided element has a vertical scrollbar.
 *
 * @param {HTMLElement} element
 * @returns {Boolean}
 */
function hasVerticalScrollbar(element) {
  return element.offsetWidth !== element.clientWidth;
}

/**
 * Checks if the provided element has a vertical scrollbar.
 *
 * @param {HTMLElement} element
 * @returns {Boolean}
 */
function hasHorizontalScrollbar(element) {
  return element.offsetHeight !== element.clientHeight;
}

/**
 * Sets overlay position depending on it's type and used browser
 */
function setOverlayPosition(overlayElem, left, top) {
  if ((0, _browser.isIE8)() || (0, _browser.isIE9)()) {
    overlayElem.style.top = top;
    overlayElem.style.left = left;
  } else if ((0, _browser.isSafari)()) {
    overlayElem.style['-webkit-transform'] = 'translate3d(' + left + ',' + top + ',0)';
  } else {
    overlayElem.style.transform = 'translate3d(' + left + ',' + top + ',0)';
  }
}

function getCssTransform(element) {
  var transform;

  if (element.style.transform && (transform = element.style.transform) !== '') {
    return ['transform', transform];
  } else if (element.style['-webkit-transform'] && (transform = element.style['-webkit-transform']) !== '') {

    return ['-webkit-transform', transform];
  }

  return -1;
}

function resetCssTransform(element) {
  if (element.style.transform && element.style.transform !== '') {
    element.style.transform = '';
  } else if (element.style['-webkit-transform'] && element.style['-webkit-transform'] !== '') {
    element.style['-webkit-transform'] = '';
  }
}

/**
 * Determines if the given DOM element is an input field.
 * Notice: By 'input' we mean input, textarea and select nodes
 *
 * @param {HTMLElement} element - DOM element
 * @returns {Boolean}
 */
function isInput(element) {
  var inputs = ['INPUT', 'SELECT', 'TEXTAREA'];

  return element && (inputs.indexOf(element.nodeName) > -1 || element.contentEditable === 'true');
}

/**
 * Determines if the given DOM element is an input field placed OUTSIDE of HOT.
 * Notice: By 'input' we mean input, textarea and select nodes
 *
 * @param {HTMLElement} element - DOM element
 * @returns {Boolean}
 */
function isOutsideInput(element) {
  return isInput(element) && element.className.indexOf('handsontableInput') == -1 && element.className.indexOf('copyPaste') == -1;
}

/***/ }),
/* 1 */
/***/ (function(module, exports, __webpack_require__) {

var global = __webpack_require__(10);
var core = __webpack_require__(45);
var hide = __webpack_require__(31);
var redefine = __webpack_require__(32);
var ctx = __webpack_require__(30);
var PROTOTYPE = 'prototype';

var $export = function (type, name, source) {
  var IS_FORCED = type & $export.F;
  var IS_GLOBAL = type & $export.G;
  var IS_STATIC = type & $export.S;
  var IS_PROTO = type & $export.P;
  var IS_BIND = type & $export.B;
  var target = IS_GLOBAL ? global : IS_STATIC ? global[name] || (global[name] = {}) : (global[name] || {})[PROTOTYPE];
  var exports = IS_GLOBAL ? core : core[name] || (core[name] = {});
  var expProto = exports[PROTOTYPE] || (exports[PROTOTYPE] = {});
  var key, own, out, exp;
  if (IS_GLOBAL) source = name;
  for (key in source) {
    // contains in native
    own = !IS_FORCED && target && target[key] !== undefined;
    // export native or passed
    out = (own ? target : source)[key];
    // bind timers to global for call from export context
    exp = IS_BIND && own ? ctx(out, global) : IS_PROTO && typeof out == 'function' ? ctx(Function.call, out) : out;
    // extend global
    if (target) redefine(target, key, out, type & $export.U);
    // export
    if (exports[key] != out) hide(exports, key, exp);
    if (IS_PROTO && expProto[key] != out) expProto[key] = out;
  }
};
global.core = core;
// type bitmap
$export.F = 1;   // forced
$export.G = 2;   // global
$export.S = 4;   // static
$export.P = 8;   // proto
$export.B = 16;  // bind
$export.W = 32;  // wrap
$export.U = 64;  // safe
$export.R = 128; // real proto method for `library`
module.exports = $export;


/***/ }),
/* 2 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


exports.__esModule = true;
exports.to2dArray = to2dArray;
exports.extendArray = extendArray;
exports.pivot = pivot;
exports.arrayReduce = arrayReduce;
exports.arrayFilter = arrayFilter;
exports.arrayMap = arrayMap;
exports.arrayEach = arrayEach;
exports.arraySum = arraySum;
exports.arrayMax = arrayMax;
exports.arrayMin = arrayMin;
exports.arrayAvg = arrayAvg;
exports.arrayFlatten = arrayFlatten;
exports.arrayUnique = arrayUnique;
function to2dArray(arr) {
  var i = 0,
      ilen = arr.length;

  while (i < ilen) {
    arr[i] = [arr[i]];
    i++;
  }
}

function extendArray(arr, extension) {
  var i = 0,
      ilen = extension.length;

  while (i < ilen) {
    arr.push(extension[i]);
    i++;
  }
}

function pivot(arr) {
  var pivotedArr = [];

  if (!arr || arr.length === 0 || !arr[0] || arr[0].length === 0) {
    return pivotedArr;
  }

  var rowCount = arr.length;
  var colCount = arr[0].length;

  for (var i = 0; i < rowCount; i++) {
    for (var j = 0; j < colCount; j++) {
      if (!pivotedArr[j]) {
        pivotedArr[j] = [];
      }

      pivotedArr[j][i] = arr[i][j];
    }
  }

  return pivotedArr;
}

/**
 * A specialized version of `.reduce` for arrays without support for callback
 * shorthands and `this` binding.
 *
 * {@link https://github.com/lodash/lodash/blob/master/lodash.js}
 *
 * @param {Array} array The array to iterate over.
 * @param {Function} iteratee The function invoked per iteration.
 * @param {*} [accumulator] The initial value.
 * @param {Boolean} [initFromArray] Specify using the first element of `array` as the initial value.
 * @returns {*} Returns the accumulated value.
 */
function arrayReduce(array, iteratee, accumulator, initFromArray) {
  var index = -1,
      length = array.length;

  if (initFromArray && length) {
    accumulator = array[++index];
  }
  while (++index < length) {
    accumulator = iteratee(accumulator, array[index], index, array);
  }

  return accumulator;
}

/**
 * A specialized version of `.filter` for arrays without support for callback
 * shorthands and `this` binding.
 *
 * {@link https://github.com/lodash/lodash/blob/master/lodash.js}
 *
 * @param {Array} array The array to iterate over.
 * @param {Function} predicate The function invoked per iteration.
 * @returns {Array} Returns the new filtered array.
 */
function arrayFilter(array, predicate) {
  var index = -1,
      length = array.length,
      resIndex = -1,
      result = [];

  while (++index < length) {
    var value = array[index];

    if (predicate(value, index, array)) {
      result[++resIndex] = value;
    }
  }

  return result;
}

/**
 * A specialized version of `.map` for arrays without support for callback
 * shorthands and `this` binding.
 *
 * @param {Array} array The array to iterate over.
 * @param {Function} iteratee The function invoked per iteration.
 * @returns {Array} Returns the new filtered array.
 */
function arrayMap(array, iteratee) {
  var index = -1,
      length = array.length,
      resIndex = -1,
      result = [];

  while (++index < length) {
    var value = array[index];

    result[++resIndex] = iteratee(value, index, array);
  }

  return result;
}

/**
 * A specialized version of `.forEach` for arrays without support for callback
 * shorthands and `this` binding.
 *
 * {@link https://github.com/lodash/lodash/blob/master/lodash.js}
 *
 * @param {Array} array The array to iterate over.
 * @param {Function} iteratee The function invoked per iteration.
 * @returns {Array} Returns `array`.
 */
function arrayEach(array, iteratee) {
  var index = -1,
      length = array.length;

  while (++index < length) {
    if (iteratee(array[index], index, array) === false) {
      break;
    }
  }

  return array;
}

/**
 * Calculate sum value for each item of the array.
 *
 * @param {Array} array The array to process.
 * @returns {Number} Returns calculated sum value.
 */
function arraySum(array) {
  return arrayReduce(array, function (a, b) {
    return a + b;
  }, 0);
}

/**
 * Returns the highest value from an array. Can be array of numbers or array of strings.
 * NOTICE: Mixed values is not supported.
 *
 * @param {Array} array The array to process.
 * @returns {Number} Returns the highest value from an array.
 */
function arrayMax(array) {
  return arrayReduce(array, function (a, b) {
    return a > b ? a : b;
  }, Array.isArray(array) ? array[0] : void 0);
}

/**
 * Returns the lowest value from an array. Can be array of numbers or array of strings.
 * NOTICE: Mixed values is not supported.
 *
 * @param {Array} array The array to process.
 * @returns {Number} Returns the lowest value from an array.
 */
function arrayMin(array) {
  return arrayReduce(array, function (a, b) {
    return a < b ? a : b;
  }, Array.isArray(array) ? array[0] : void 0);
}

/**
 * Calculate average value for each item of the array.
 *
 * @param {Array} array The array to process.
 * @returns {Number} Returns calculated average value.
 */
function arrayAvg(array) {
  if (!array.length) {
    return 0;
  }

  return arraySum(array) / array.length;
}

/**
 * Flatten multidimensional array.
 *
 * @param {Array} array Array of Arrays
 * @returns {Array}
 */
function arrayFlatten(array) {
  return arrayReduce(array, function (initial, value) {
    return initial.concat(Array.isArray(value) ? arrayFlatten(value) : value);
  }, []);
}

/**
 * Unique values in the array.
 *
 * @param {Array} array The array to process.
 * @returns {Array}
 */
function arrayUnique(array) {
  var unique = [];

  arrayEach(array, function (value) {
    if (unique.indexOf(value) === -1) {
      unique.push(value);
    }
  });

  return unique;
}

/***/ }),
/* 3 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


exports.__esModule = true;

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

exports.duckSchema = duckSchema;
exports.inherit = inherit;
exports.extend = extend;
exports.deepExtend = deepExtend;
exports.deepClone = deepClone;
exports.clone = clone;
exports.mixin = mixin;
exports.isObjectEquals = isObjectEquals;
exports.isObject = isObject;
exports.defineGetter = defineGetter;
exports.objectEach = objectEach;
exports.getProperty = getProperty;
exports.deepObjectSize = deepObjectSize;
exports.createObjectPropListener = createObjectPropListener;
exports.hasOwnProperty = hasOwnProperty;

var _array = __webpack_require__(2);

function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }

/**
 * Generate schema for passed object.
 *
 * @param {Array|Object} object
 * @returns {Array|Object}
 */
function duckSchema(object) {
  var schema;

  if (Array.isArray(object)) {
    schema = [];
  } else {
    schema = {};

    objectEach(object, function (value, key) {
      if (key === '__children') {
        return;
      }

      if (value && (typeof value === 'undefined' ? 'undefined' : _typeof(value)) === 'object' && !Array.isArray(value)) {
        schema[key] = duckSchema(value);
      } else if (Array.isArray(value)) {
        if (value.length && _typeof(value[0]) === 'object' && !Array.isArray(value[0])) {
          schema[key] = [duckSchema(value[0])];
        } else {
          schema[key] = [];
        }
      } else {
        schema[key] = null;
      }
    });
  }

  return schema;
}

/**
 * Inherit without without calling parent constructor, and setting `Child.prototype.constructor` to `Child` instead of `Parent`.
 * Creates temporary dummy function to call it as constructor.
 * Described in ticket: https://github.com/handsontable/handsontable/pull/516
 *
 * @param  {Object} Child  child class
 * @param  {Object} Parent parent class
 * @return {Object}        extended Child
 */
function inherit(Child, Parent) {
  Parent.prototype.constructor = Parent;
  Child.prototype = new Parent();
  Child.prototype.constructor = Child;

  return Child;
}

/**
 * Perform shallow extend of a target object with extension's own properties.
 *
 * @param {Object} target An object that will receive the new properties.
 * @param {Object} extension An object containing additional properties to merge into the target.
 */
function extend(target, extension) {
  objectEach(extension, function (value, key) {
    target[key] = value;
  });

  return target;
}

/**
 * Perform deep extend of a target object with extension's own properties.
 *
 * @param {Object} target An object that will receive the new properties.
 * @param {Object} extension An object containing additional properties to merge into the target.
 */
function deepExtend(target, extension) {
  objectEach(extension, function (value, key) {
    if (extension[key] && _typeof(extension[key]) === 'object') {
      if (!target[key]) {
        if (Array.isArray(extension[key])) {
          target[key] = [];
        } else if (Object.prototype.toString.call(extension[key]) === '[object Date]') {
          target[key] = extension[key];
        } else {
          target[key] = {};
        }
      }
      deepExtend(target[key], extension[key]);
    } else {
      target[key] = extension[key];
    }
  });
}

/**
 * Perform deep clone of an object.
 * WARNING! Only clones JSON properties. Will cause error when `obj` contains a function, Date, etc.
 *
 * @param {Object} obj An object that will be cloned
 * @return {Object}
 */
function deepClone(obj) {
  if ((typeof obj === 'undefined' ? 'undefined' : _typeof(obj)) === 'object') {
    return JSON.parse(JSON.stringify(obj));
  }

  return obj;
}

/**
 * Shallow clone object.
 *
 * @param {Object} object
 * @returns {Object}
 */
function clone(object) {
  var result = {};

  objectEach(object, function (value, key) {
    result[key] = value;
  });

  return result;
}

/**
 * Extend the Base object (usually prototype) of the functionality the `mixins` objects.
 *
 * @param {Object} Base Base object which will be extended.
 * @param {Object} mixins The object of the functionality will be "copied".
 * @returns {Object}
 */
function mixin(Base) {
  if (!Base.MIXINS) {
    Base.MIXINS = [];
  }

  for (var _len = arguments.length, mixins = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
    mixins[_key - 1] = arguments[_key];
  }

  (0, _array.arrayEach)(mixins, function (mixin) {
    Base.MIXINS.push(mixin.MIXIN_NAME);

    objectEach(mixin, function (value, key) {
      if (Base.prototype[key] !== void 0) {
        throw new Error('Mixin conflict. Property \'' + key + '\' already exist and cannot be overwritten.');
      }
      if (typeof value === 'function') {
        Base.prototype[key] = value;
      } else {
        var getter = function _getter(propertyName, initialValue) {
          propertyName = '_' + propertyName;

          var initValue = function initValue(value) {
            if (Array.isArray(value) || isObject(value)) {
              value = deepClone(value);
            }

            return value;
          };

          return function () {
            if (this[propertyName] === void 0) {
              this[propertyName] = initValue(initialValue);
            }

            return this[propertyName];
          };
        };
        var setter = function _setter(propertyName) {
          propertyName = '_' + propertyName;

          return function (value) {
            this[propertyName] = value;
          };
        };
        Object.defineProperty(Base.prototype, key, {
          get: getter(key, value),
          set: setter(key),
          configurable: true
        });
      }
    });
  });

  return Base;
}

/**
 * Checks if two objects or arrays are (deep) equal
 *
 * @param {Object|Array} object1
 * @param {Object|Array} object2
 * @returns {Boolean}
 */
function isObjectEquals(object1, object2) {
  return JSON.stringify(object1) === JSON.stringify(object2);
}

/**
 * Determines whether given object is a plain Object.
 * Note: String and Array are not plain Objects
 * @param {*} obj
 * @returns {boolean}
 */
function isObject(obj) {
  return Object.prototype.toString.call(obj) == '[object Object]';
}

function defineGetter(object, property, value, options) {
  options.value = value;
  options.writable = options.writable !== false;
  options.enumerable = options.enumerable !== false;
  options.configurable = options.configurable !== false;

  Object.defineProperty(object, property, options);
}

/**
 * A specialized version of `.forEach` for objects.
 *
 * @param {Object} object The object to iterate over.
 * @param {Function} iteratee The function invoked per iteration.
 * @returns {Object} Returns `object`.
 */
function objectEach(object, iteratee) {
  for (var key in object) {
    if (!object.hasOwnProperty || object.hasOwnProperty && Object.prototype.hasOwnProperty.call(object, key)) {
      if (iteratee(object[key], key, object) === false) {
        break;
      }
    }
  }

  return object;
}

/**
 * Get object property by its name. Access to sub properties can be achieved by dot notation (e.q. `'foo.bar.baz'`).
 *
 * @param {Object} object Object which value will be exported.
 * @param {String} name Object property name.
 * @returns {*}
 */
function getProperty(object, name) {
  var names = name.split('.');
  var result = object;

  objectEach(names, function (name) {
    result = result[name];

    if (result === void 0) {
      result = void 0;

      return false;
    }
  });

  return result;
}

/**
 * Return object length (recursively).
 *
 * @param {*} object Object for which we want get length.
 * @returns {Number}
 */
function deepObjectSize(object) {
  if (!isObject(object)) {
    return 0;
  }
  var recursObjLen = function recursObjLen(obj) {
    var result = 0;

    if (isObject(obj)) {
      objectEach(obj, function (key) {
        result += recursObjLen(key);
      });
    } else {
      result++;
    }

    return result;
  };

  return recursObjLen(object);
}

/**
 * Create object with property where its value change will be observed.
 *
 * @param {*} [defaultValue=undefined] Default value.
 * @param {String} [propertyToListen='value'] Property to listen.
 * @returns {Object}
 */
function createObjectPropListener(defaultValue) {
  var _holder;

  var propertyToListen = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'value';

  var privateProperty = '_' + propertyToListen;
  var holder = (_holder = {
    _touched: false
  }, _defineProperty(_holder, privateProperty, defaultValue), _defineProperty(_holder, 'isTouched', function isTouched() {
    return this._touched;
  }), _holder);

  Object.defineProperty(holder, propertyToListen, {
    get: function get() {
      return this[privateProperty];
    },
    set: function set(value) {
      this._touched = true;
      this[privateProperty] = value;
    },

    enumerable: true,
    configurable: true
  });

  return holder;
}

/**
 * Check if at specified `key` there is any value for `object`.
 *
 * @param {Object} object Object to search value at specyfic key.
 * @param {String} key String key to check.
 */
function hasOwnProperty(object, key) {
  return Object.prototype.hasOwnProperty.call(object, key);
}

/***/ }),
/* 4 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


exports.__esModule = true;

var _createClass = 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); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

exports.getListenersCounter = getListenersCounter;

var _element = __webpack_require__(0);

var _object = __webpack_require__(3);

var _feature = __webpack_require__(34);

var _event = __webpack_require__(7);

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

/**
 * Counter which tracks unregistered listeners (useful for detecting memory leaks).
 *
 * @type {Number}
 */
var listenersCounter = 0;

/**
 * Event DOM manager for internal use in Handsontable.
 *
 * @class EventManager
 * @util
 */

var EventManager = function () {
  /**
   * @param {Object} [context=null]
   * @private
   */
  function EventManager() {
    var context = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;

    _classCallCheck(this, EventManager);

    this.context = context || this;

    if (!this.context.eventListeners) {
      this.context.eventListeners = [];
    }
  }

  /**
   * Register specified listener (`eventName`) to the element.
   *
   * @param {Element} element Target element.
   * @param {String} eventName Event name.
   * @param {Function} callback Function which will be called after event occur.
   * @returns {Function} Returns function which you can easily call to remove that event
   */


  _createClass(EventManager, [{
    key: 'addEventListener',
    value: function addEventListener(element, eventName, callback) {
      var _this = this;

      var context = this.context;

      function callbackProxy(event) {
        event = extendEvent(context, event);

        callback.call(this, event);
      }
      this.context.eventListeners.push({
        element: element,
        event: eventName,
        callback: callback,
        callbackProxy: callbackProxy
      });

      if (window.addEventListener) {
        element.addEventListener(eventName, callbackProxy, false);
      } else {
        element.attachEvent('on' + eventName, callbackProxy);
      }
      listenersCounter++;

      return function () {
        _this.removeEventListener(element, eventName, callback);
      };
    }

    /**
     * Remove the event listener previously registered.
     *
     * @param {Element} element Target element.
     * @param {String} eventName Event name.
     * @param {Function} callback Function to remove from the event target. It must be the same as during registration listener.
     */

  }, {
    key: 'removeEventListener',
    value: function removeEventListener(element, eventName, callback) {
      var len = this.context.eventListeners.length;
      var tmpEvent = void 0;

      while (len--) {
        tmpEvent = this.context.eventListeners[len];

        if (tmpEvent.event == eventName && tmpEvent.element == element) {
          if (callback && callback != tmpEvent.callback) {
            /* eslint-disable no-continue */
            continue;
          }
          this.context.eventListeners.splice(len, 1);

          if (tmpEvent.element.removeEventListener) {
            tmpEvent.element.removeEventListener(tmpEvent.event, tmpEvent.callbackProxy, false);
          } else {
            tmpEvent.element.detachEvent('on' + tmpEvent.event, tmpEvent.callbackProxy);
          }
          listenersCounter--;
        }
      }
    }

    /**
     * Clear all previously registered events.
     *
     * @private
     * @since 0.15.0-beta3
     */

  }, {
    key: 'clearEvents',
    value: function clearEvents() {
      if (!this.context) {
        return;
      }
      var len = this.context.eventListeners.length;

      while (len--) {
        var event = this.context.eventListeners[len];

        if (event) {
          this.removeEventListener(event.element, event.event, event.callback);
        }
      }
    }

    /**
     * Clear all previously registered events.
     */

  }, {
    key: 'clear',
    value: function clear() {
      this.clearEvents();
    }

    /**
     * Destroy instance of EventManager.
     */

  }, {
    key: 'destroy',
    value: function destroy() {
      this.clearEvents();
      this.context = null;
    }

    /**
     * Trigger event at the specified target element.
     *
     * @param {Element} element Target element.
     * @param {String} eventName Event name.
     */

  }, {
    key: 'fireEvent',
    value: function fireEvent(element, eventName) {
      var options = {
        bubbles: true,
        cancelable: eventName !== 'mousemove',
        view: window,
        detail: 0,
        screenX: 0,
        screenY: 0,
        clientX: 1,
        clientY: 1,
        ctrlKey: false,
        altKey: false,
        shiftKey: false,
        metaKey: false,
        button: 0,
        relatedTarget: undefined
      };
      var event;

      if (document.createEvent) {
        event = document.createEvent('MouseEvents');
        event.initMouseEvent(eventName, options.bubbles, options.cancelable, options.view, options.detail, options.screenX, options.screenY, options.clientX, options.clientY, options.ctrlKey, options.altKey, options.shiftKey, options.metaKey, options.button, options.relatedTarget || document.body.parentNode);
      } else {
        event = document.createEventObject();
      }

      if (element.dispatchEvent) {
        element.dispatchEvent(event);
      } else {
        element.fireEvent('on' + eventName, event);
      }
    }
  }]);

  return EventManager;
}();

/**
 * @param {Object} context
 * @param {Event} event
 * @private
 * @returns {*}
 */


function extendEvent(context, event) {
  var componentName = 'HOT-TABLE';
  var isHotTableSpotted = void 0;
  var fromElement = void 0;
  var realTarget = void 0;
  var target = void 0;
  var len = void 0;
  var nativeStopImmediatePropagation = void 0;

  event.isTargetWebComponent = false;
  event.realTarget = event.target;

  nativeStopImmediatePropagation = event.stopImmediatePropagation;
  event.stopImmediatePropagation = function () {
    nativeStopImmediatePropagation.apply(this);
    (0, _event.stopImmediatePropagation)(this);
  };

  if (!EventManager.isHotTableEnv) {
    return event;
  }
  event = (0, _element.polymerWrap)(event);
  len = event.path ? event.path.length : 0;

  while (len--) {
    if (event.path[len].nodeName === componentName) {
      isHotTableSpotted = true;
    } else if (isHotTableSpotted && event.path[len].shadowRoot) {
      target = event.path[len];

      break;
    }
    if (len === 0 && !target) {
      target = event.path[len];
    }
  }
  if (!target) {
    target = event.target;
  }
  event.isTargetWebComponent = true;

  if ((0, _feature.isWebComponentSupportedNatively)()) {
    event.realTarget = event.srcElement || event.toElement;
  } else if ((0, _object.hasOwnProperty)(context, 'hot') || context.isHotTableEnv || context.wtTable) {
    // Polymer doesn't support `event.target` property properly we must emulate it ourselves
    if ((0, _object.hasOwnProperty)(context, 'hot')) {
      // Custom element
      fromElement = context.hot ? context.hot.view.wt.wtTable.TABLE : null;
    } else if (context.isHotTableEnv) {
      // Handsontable.Core
      fromElement = context.view.activeWt.wtTable.TABLE.parentNode.parentNode;
    } else if (context.wtTable) {
      // Walkontable
      fromElement = context.wtTable.TABLE.parentNode.parentNode;
    }
    realTarget = (0, _element.closest)(event.target, [componentName], fromElement);

    if (realTarget) {
      event.realTarget = fromElement.querySelector(componentName) || event.target;
    } else {
      event.realTarget = event.target;
    }
  }

  Object.defineProperty(event, 'target', {
    get: function get() {
      return (0, _element.polymerWrap)(target);
    },

    enumerable: true,
    configurable: true
  });

  return event;
}

exports.default = EventManager;
function getListenersCounter() {
  return listenersCounter;
};

/***/ }),
/* 5 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


exports.__esModule = true;

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

exports.isNumeric = isNumeric;
exports.rangeEach = rangeEach;
exports.rangeEachReverse = rangeEachReverse;
exports.valueAccordingPercent = valueAccordingPercent;
/**
 * Checks if value of n is a numeric one
 * http://jsperf.com/isnan-vs-isnumeric/4
 * @param n
 * @returns {boolean}
 */
function isNumeric(n) {
  /* eslint-disable */
  var t = typeof n === 'undefined' ? 'undefined' : _typeof(n);

  return t == 'number' ? !isNaN(n) && isFinite(n) : t == 'string' ? !n.length ? false : n.length == 1 ? /\d/.test(n) : /^\s*[+-]?\s*(?:(?:\d+(?:\.\d+)?(?:e[+-]?\d+)?)|(?:0x[a-f\d]+))\s*$/i.test(n) : t == 'object' ? !!n && typeof n.valueOf() == 'number' && !(n instanceof Date) : false;
}

/**
 * A specialized version of `.forEach` defined by ranges.
 *
 * @param {Number} rangeFrom The number from start iterate.
 * @param {Number|Function} rangeTo The number where finish iterate or function as a iteratee.
 * @param {Function} [iteratee] The function invoked per iteration.
 */
function rangeEach(rangeFrom, rangeTo, iteratee) {
  var index = -1;

  if (typeof rangeTo === 'function') {
    iteratee = rangeTo;
    rangeTo = rangeFrom;
  } else {
    index = rangeFrom - 1;
  }
  while (++index <= rangeTo) {
    if (iteratee(index) === false) {
      break;
    }
  }
}

/**
 * A specialized version of `.forEach` defined by ranges iterable in reverse order.
 *
 * @param {Number} rangeFrom The number from start iterate.
 * @param {Number} rangeTo The number where finish iterate.
 * @param {Function} iteratee The function invoked per iteration.
 */
function rangeEachReverse(rangeFrom, rangeTo, iteratee) {
  var index = rangeFrom + 1;

  if (typeof rangeTo === 'function') {
    iteratee = rangeTo;
    rangeTo = 0;
  }
  while (--index >= rangeTo) {
    if (iteratee(index) === false) {
      break;
    }
  }
}

/**
 * Calculate value from percent.
 *
 * @param {Number} value Base value from percent will be calculated.
 * @param {String|Number} percent Can be Number or String (eq. `'33%'`).
 * @returns {Number}
 */
function valueAccordingPercent(value, percent) {
  percent = parseInt(percent.toString().replace('%', ''), 10);
  percent = parseInt(value * percent / 100, 10);

  return percent;
}

/***/ }),
/* 6 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


exports.__esModule = true;
exports.getRegisteredRenderers = exports.getRegisteredRendererNames = exports.hasRenderer = exports.getRenderer = exports.registerRenderer = undefined;

var _staticRegister2 = __webpack_require__(53);

var _staticRegister3 = _interopRequireDefault(_staticRegister2);

var _cellDecorator = __webpack_require__(376);

var _cellDecorator2 = _interopRequireDefault(_cellDecorator);

var _autocompleteRenderer = __webpack_require__(377);

var _autocompleteRenderer2 = _interopRequireDefault(_autocompleteRenderer);

var _checkboxRenderer = __webpack_require__(378);

var _checkboxRenderer2 = _interopRequireDefault(_checkboxRenderer);

var _htmlRenderer = __webpack_require__(379);

var _htmlRenderer2 = _interopRequireDefault(_htmlRenderer);

var _numericRenderer = __webpack_require__(380);

var _numericRenderer2 = _interopRequireDefault(_numericRenderer);

var _passwordRenderer = __webpack_require__(381);

var _passwordRenderer2 = _interopRequireDefault(_passwordRenderer);

var _textRenderer = __webpack_require__(382);

var _textRenderer2 = _interopRequireDefault(_textRenderer);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

var _staticRegister = (0, _staticRegister3.default)('renderers'),
    register = _staticRegister.register,
    getItem = _staticRegister.getItem,
    hasItem = _staticRegister.hasItem,
    getNames = _staticRegister.getNames,
    getValues = _staticRegister.getValues;

register('base', _cellDecorator2.default);
register('autocomplete', _autocompleteRenderer2.default);
register('checkbox', _checkboxRenderer2.default);
register('html', _htmlRenderer2.default);
register('numeric', _numericRenderer2.default);
register('password', _passwordRenderer2.default);
register('text', _textRenderer2.default);

/**
 * Retrieve renderer function.
 *
 * @param {String} name Renderer identification.
 * @returns {Function} Returns renderer function.
 */
function _getItem(name) {
  if (typeof name === 'function') {
    return name;
  }
  if (!hasItem(name)) {
    throw Error('No registered renderer found under "' + name + '" name');
  }

  return getItem(name);
}

exports.registerRenderer = register;
exports.getRenderer = _getItem;
exports.hasRenderer = hasItem;
exports.getRegisteredRendererNames = getNames;
exports.getRegisteredRenderers = getValues;

/***/ }),
/* 7 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


exports.__esModule = true;
exports.stopImmediatePropagation = stopImmediatePropagation;
exports.isImmediatePropagationStopped = isImmediatePropagationStopped;
exports.stopPropagation = stopPropagation;
exports.pageX = pageX;
exports.pageY = pageY;
exports.isRightClick = isRightClick;
exports.isLeftClick = isLeftClick;

var _element = __webpack_require__(0);

/**
 * Prevent other listeners of the same event from being called.
 *
 * @param {Event} event
 */
function stopImmediatePropagation(event) {
  event.isImmediatePropagationEnabled = false;
  event.cancelBubble = true;
}

/**
 * Check if event was stopped by `stopImmediatePropagation`.
 *
 * @param event {Event}
 * @returns {Boolean}
 */
function isImmediatePropagationStopped(event) {
  return event.isImmediatePropagationEnabled === false;
}

/**
 * Prevent further propagation of the current event (prevent bubbling).
 *
 * @param event {Event}
 */
function stopPropagation(event) {
  // ie8
  // http://msdn.microsoft.com/en-us/library/ie/ff975462(v=vs.85).aspx
  if (typeof event.stopPropagation === 'function') {
    event.stopPropagation();
  } else {
    event.cancelBubble = true;
  }
}

/**
 * Get horizontal coordinate of the event object relative to the whole document.
 *
 * @param {Event} event
 * @returns {Number}
 */
function pageX(event) {
  if (event.pageX) {
    return event.pageX;
  }

  return event.clientX + (0, _element.getWindowScrollLeft)();
}

/**
 * Get vertical coordinate of the event object relative to the whole document.
 *
 * @param {Event} event
 * @returns {Number}
 */
function pageY(event) {
  if (event.pageY) {
    return event.pageY;
  }

  return event.clientY + (0, _element.getWindowScrollTop)();
}

/**
 * Check if provided event was triggered by clicking the right mouse button.
 *
 * @param {Event} event DOM Event.
 * @returns {Boolean}
 */
function isRightClick(event) {
  return event.button === 2;
}

/**
 * Check if provided event was triggered by clicking the left mouse button.
 *
 * @param {Event} event DOM Event.
 * @returns {Boolean}
 */
function isLeftClick(event) {
  return event.button === 0;
}

/***/ }),
/* 8 */
/***/ (function(module, exports, __webpack_require__) {

var store = __webpack_require__(84)('wks');
var uid = __webpack_require__(51);
var Symbol = __webpack_require__(10).Symbol;
var USE_SYMBOL = typeof Symbol == 'function';

var $exports = module.exports = function (name) {
  return store[name] || (store[name] =
    USE_SYMBOL && Symbol[name] || (USE_SYMBOL ? Symbol : uid)('Symbol.' + name));
};

$exports.store = store;


/***/ }),
/* 9 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


exports.__esModule = true;
exports.getPluginName = exports.getRegistredPluginNames = exports.getPlugin = exports.registerPlugin = undefined;

var _pluginHooks = __webpack_require__(11);

var _pluginHooks2 = _interopRequireDefault(_pluginHooks);

var _object = __webpack_require__(3);

var _string = __webpack_require__(28);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

var registeredPlugins = new WeakMap();

/**
 * Registers plugin under given name
 *
 * @param {String} pluginName
 * @param {Function} PluginClass
 */
/**
 * Utility to register plugins and common namespace for keeping reference to all plugins classes
 */
function registerPlugin(pluginName, PluginClass) {
  pluginName = (0, _string.toUpperCaseFirst)(pluginName);

  _pluginHooks2.default.getSingleton().add('construct', function () {
    var holder = void 0;

    if (!registeredPlugins.has(this)) {
      registeredPlugins.set(this, {});
    }
    holder = registeredPlugins.get(this);

    if (!holder[pluginName]) {
      holder[pluginName] = new PluginClass(this);
    }
  });
  _pluginHooks2.default.getSingleton().add('afterDestroy', function () {
    if (registeredPlugins.has(this)) {
      var pluginsHolder = registeredPlugins.get(this);

      (0, _object.objectEach)(pluginsHolder, function (plugin) {
        return plugin.destroy();
      });
      registeredPlugins.delete(this);
    }
  });
}

/**
 * @param {Object} instance
 * @param {String|Function} pluginName
 * @returns {Function} pluginClass Returns plugin instance if exists or `undefined` if not exists.
 */
function getPlugin(instance, pluginName) {
  if (typeof pluginName != 'string') {
    throw Error('Only strings can be passed as "plugin" parameter');
  }
  var _pluginName = (0, _string.toUpperCaseFirst)(pluginName);

  if (!registeredPlugins.has(instance) || !registeredPlugins.get(instance)[_pluginName]) {
    return void 0;
  }

  return registeredPlugins.get(instance)[_pluginName];
}

/**
 * Get all registred plugins names for concrete Handsontable instance.
 *
 * @param {Object} hotInstance
 * @returns {Array}
 */
function getRegistredPluginNames(hotInstance) {
  return registeredPlugins.has(hotInstance) ? Object.keys(registeredPlugins.get(hotInstance)) : [];
}

/**
 * Get plugin name.
 *
 * @param {Object} hotInstance
 * @param {Object} plugin
 * @returns {String|null}
 */
function getPluginName(hotInstance, plugin) {
  var pluginName = null;

  if (registeredPlugins.has(hotInstance)) {
    (0, _object.objectEach)(registeredPlugins.get(hotInstance), function (pluginInstance, name) {
      if (pluginInstance === plugin) {
        pluginName = name;
      }
    });
  }

  return pluginName;
}

exports.registerPlugin = registerPlugin;
exports.getPlugin = getPlugin;
exports.getRegistredPluginNames = getRegistredPluginNames;
exports.getPluginName = getPluginName;

/***/ }),
/* 10 */
/***/ (function(module, exports) {

// https://github.com/zloirock/core-js/issues/86#issuecomment-115759028
var global = module.exports = typeof window != 'undefined' && window.Math == Math
  ? window : typeof self != 'undefined' && self.Math == Math ? self
  // eslint-disable-next-line no-new-func
  : Function('return this')();
if (typeof __g == 'number') __g = global; // eslint-disable-line no-undef


/***/ }),
/* 11 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


exports.__esModule = true;

var _createClass = 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); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

var _array = __webpack_require__(2);

var _object = __webpack_require__(3);

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

/**
 * @description
 * Handsontable events are the common interface that function in 2 ways: as __callbacks__ and as __hooks__.
 *
 * @example
 *
 * ```js
 * // Using events as callbacks:
 * ...
 * var hot1 = new Handsontable(document.getElementById('example1'), {
 *   afterChange: function(changes, source) {
 *     $.ajax({
 *       url: "save.php',
 *       data: change
 *     });
 *   }
 * });
 * ...
 * ```
 *
 * ```js
 * // Using events as plugin hooks:
 * ...
 * var hot1 = new Handsontable(document.getElementById('example1'), {
 *   myPlugin: true
 * });
 *
 * var hot2 = new Handsontable(document.getElementById('example2'), {
 *   myPlugin: false
 * });
 *
 * // global hook
 * Handsontable.hooks.add('afterChange', function() {
 *   // Fired twice - for hot1 and hot2
 *   if (this.getSettings().myPlugin) {
 *     // function body - will only run for hot1
 *   }
 * });
 *
 * // local hook (has same effect as a callback)
 * hot2.addHook('afterChange', function() {
 *   // function body - will only run in #example2
 * });
 * ```
 * ...
 */

// @TODO: Move plugin description hooks to plugin?
var REGISTERED_HOOKS = [
/**
 * Callback fired after resetting a cell's meta.
 *
 * @event Hooks#afterCellMetaReset
 * @since 0.11
 */
'afterCellMetaReset',

/**
 * @description
 * Callback fired after one or more cells has been changed. Its main use case is to save the input.
 *
 * __Note:__ For performance reasons, the `changes` array is null for `"loadData"` source.
 *
 * @event Hooks#afterChange
 * @param {Array} changes 2D array containing information about each of the edited cells `[[row, prop, oldVal, newVal], ...]`.
 * @param {String} [source] String that identifies source of hook call
 *                          ([list of all available sources]{@link http://docs.handsontable.com/tutorial-using-callbacks.html#page-source-definition}).
 */
'afterChange',

/**
 * @description
 * Fired after observing changes.
 *
 * @event Hooks#afterChangesObserved
 */
'afterChangesObserved',

/**
 * @description
 * Fired after setting up the Context Menu's default options. These options are a collection which user can select by setting
 * an array of keys or an array of objects in `contextMenu` option.
 *
 * @event Hooks#afterContextMenuDefaultOptions
 * @param {Array} predefinedItems Array of objects containing information about the pre-defined Context Menu items.
 */
'afterContextMenuDefaultOptions',

/**
 * @description
 * Fired before setting up the Context Menu's items but after filtering these options by user (`contextMenu` option). This hook
 * can by helpful to determine if user use specified menu item or to set up one of the menu item to by always visible.
 *
 * @event Hooks#beforeContextMenuSetItems
 * @param {Array} menuItems Array of objects containing information about to generated Context Menu items.
 */
'beforeContextMenuSetItems',

/**
 * @description
 * Fired after setting up the Context Menu's default options. These options are a collection which user can select by setting
 * an array of keys or an array of objects in `contextMenu` option.
 *
 * @pro
 * @event Hooks#afterDropdownMenuDefaultOptions
 * @param {Array} predefinedItems Array of objects containing information about the pre-defined Context Menu items.
 */
'afterDropdownMenuDefaultOptions',

/**
 * @description
 * Fired before setting up the Dropdown Menu's items but after filtering these options by user (`dropdownMenu` option). This hook
 * can by helpful to determine if user use specified menu item or to set up one of the menu item to by always visible.
 *
 * @pro
 * @event Hooks#beforeDropdownMenuSetItems
 * @param {Array} menuItems Array of objects containing information about to generated Dropdown Menu items.
 */
'beforeDropdownMenuSetItems',

/**
 * @description
 * Fired after hiding the Context Menu.
 *
 * @event Hooks#afterContextMenuHide
 * @param {Object} context The Context menu instance.
 */
'afterContextMenuHide',

/**
 * @description
 * Fired after opening the Context Menu.
 *
 * @event Hooks#afterContextMenuShow
 * @param {Object} context The Context Menu instance.
 */
'afterContextMenuShow',

/**
 * @description
 * Fired after reaching the copy limit while copying data.
 *
 * @event Hooks#afterCopyLimit
 * @param {Number} selectedRows Count of selected copyable rows.
 * @param {Number} selectedColumns Count of selected copyable columns.
 * @param {Number} copyRowsLimit Current copy rows limit.
 * @param {Number} copyColumnsLimit Current copy columns limit.
 */
'afterCopyLimit',

/**
 * Callback is fired before a new column was created.
 *
 * @since 0.28.0
 * @event Hooks#beforeCreateCol
 * @param {Number} index Represents the visual index of first newly created column in the data source array.
 * @param {Number} amount Number of newly created columns in the data source array.
 * @param {String} [source] String that identifies source of hook call
 *                          ([list of all available sources]{@link http://docs.handsontable.com/tutorial-using-callbacks.html#page-source-definition}).
 */
'beforeCreateCol',

/**
 * Callback is fired after a new column was created.
 *
 * @event Hooks#afterCreateCol
 * @param {Number} index Represents the visual index of first newly created column in the data source array.
 * @param {Number} amount Number of newly created columns in the data source array.
 * @param {String} [source] String that identifies source of hook call
 *                          ([list of all available sources]{@link http://docs.handsontable.com/tutorial-using-callbacks.html#page-source-definition}).
 */
'afterCreateCol',

/**
 * Callback is fired before a new row was created.
 *
 * @since 0.28.0
 * @event Hooks#beforeCreateRow
 * @param {Number} index Represents the visual index of first newly created row in the data source array.
 * @param {Number} amount Number of newly created rows in the data source array.
 * @param {String} [source] String that identifies source of hook call
 *                          ([list of all available sources]{@link http://docs.handsontable.com/tutorial-using-callbacks.html#page-source-definition}).
 */
'beforeCreateRow',

/**
 * Callback is fired after a new row was created.
 *
 * @event Hooks#afterCreateRow
 * @param {Number} index Represents the visual index of first newly created row in the data source array.
 * @param {Number} amount Number of newly created rows in the data source array.
 * @param {String} [source] String that identifies source of hook call
 *                          ([list of all available sources]{@link http://docs.handsontable.com/tutorial-using-callbacks.html#page-source-definition}).
 */
'afterCreateRow',

/**
 * Fired after the current cell is deselected.
 *
 * @event Hooks#afterDeselect
 */
'afterDeselect',

/**
 * Fired after destroying the Handsontable instance.
 *
 * @event Hooks#afterDestroy
 */
'afterDestroy',

/**
 * Fired on a `keydown` event on the document body.
 *
 * @event Hooks#afterDocumentKeyDown
 * @param {Event} event A `keydown` event.
 */
'afterDocumentKeyDown',

/**
 * Callback fired after getting the cell settings.
 *
 * @event Hooks#afterGetCellMeta
 * @param {Number} row Visual row index.
 * @param {Number} col Visual column index.
 * @param {Object} cellProperties Object containing the cell properties.
 */
'afterGetCellMeta',

/**
 * Callback fired after retrieving information about a column header and appending it to the table header.
 *
 * @event Hooks#afterGetColHeader
 * @param {Number} col Visual column index.
 * @param {Element} TH Header's TH element.
 */
'afterGetColHeader',

/**
 * Callback fired after retrieving information about a column header and appending it to the table header.
 *
 * @event Hooks#afterGetRowHeader
 * @param {Number} row Visual row index.
 * @param {Element} TH Header's TH element.
 */
'afterGetRowHeader',

/**
 * Callback fired after Handsontable instance is initiated.
 *
 * @event Hooks#afterInit
 */
'afterInit',

/**
 * Callback fired after new data is loaded (by `loadData` method) into the data source array.
 *
 * @event Hooks#afterLoadData
 * @param {Boolean} firstTime flag that determines whether the data has been loaded during the initialization.
 */
'afterLoadData',

/**
 * Fired after a scroll event, which is identified as a momentum scroll (e.g. on an iPad).
 *
 * @event Hooks#afterMomentumScroll
 */
'afterMomentumScroll',

/**
 * Fired after a `mousedown` event is triggered on the cell corner (the drag handle).
 *
 * @event Hooks#afterOnCellCornerMouseDown
 * @since 0.11
 * @param {Object} event `mousedown` event object.
 */
'afterOnCellCornerMouseDown',

/**
 * Fired after a `dblclick` event is triggered on the cell corner (the drag handle).
 *
 * @event Hooks#afterOnCellCornerDblClick
 * @since 0.30.0
 * @param {Object} event `dblclick` event object.
 */
'afterOnCellCornerDblClick',

/**
 * Callback fired after clicking on a cell or row/column header.
 * In case the row/column header was clicked, the index is negative.
 * For example clicking on the row header of cell (0, 0) results with `afterOnCellMouseDown` called
 * with coords `{row: 0, col: -1}`.
 *
 * @event Hooks#afterOnCellMouseDown
 * @since 0.11
 * @param {Object} event `mousedown` event object.
 * @param {Object} coords Coordinates object containing the visual row and visual column indexes of the clicked cell.
 * @param {Element} TD Cell's TD (or TH) element.
 */
'afterOnCellMouseDown',

/**
 * Callback fired after hovering a cell or row/column header with the mouse cursor.
 * In case the row/column header was hovered, the index is negative.
 * For example, hovering over the row header of cell (0, 0) results with `afterOnCellMouseOver` called
 * with coords `{row: 0, col: -1}`.
 *
 * @event Hooks#afterOnCellMouseOver
 * @since 0.11
 * @param {Object} event `mouseover` event object.
 * @param {Object} coords Hovered cell's visual coordinate object.
 * @param {Element} TD Cell's TD (or TH) element.
 */
'afterOnCellMouseOver',

/**
 * Callback fired after leaving a cell or row/column header with the mouse cursor.
 *
 * @event Hooks#afterOnCellMouseOut
 * @since 0.31.1
 * @param {Object} event `mouseout` event object.
 * @param {Object} coords Leaved cell's visual coordinate object.
 * @param {Element} TD Cell's TD (or TH) element.
 */
'afterOnCellMouseOut',

/**
 * Callback is fired when one or more columns are removed.
 *
 * @event Hooks#afterRemoveCol
 * @param {Number} index Is an visual index of starter column.
 * @param {Number} amount Is an amount of removed columns.
 */
'afterRemoveCol',

/**
 * Callback is fired when one or more rows are removed.
 *
 * @event Hooks#afterRemoveRow
 * @param {Number} index Is an visual index of starter row.
 * @param {Number} amount Is an amount of removed rows.
 */
'afterRemoveRow',

/**
 * Callback fired after the Handsontable table is rendered.
 *
 * @event Hooks#afterRender
 * @param {Boolean} isForced Is `true` if rendering was triggered by a change of settings or data; or `false` if
 *                           rendering was triggered by scrolling or moving selection.
 */
'afterRender',

/**
 * Fired before starting rendering the cell.
 *
 * @event Hooks#beforeRenderer
 * @since 0.24.2
 * @param {Element} TD Currently rendered cell's TD element.
 * @param {Number} row Visual row index.
 * @param {Number} col Visual column index.
 * @param {String|Number} prop Column property name or a column index, if datasource is an array of arrays.
 * @param {String} value Value of the rendered cell.
 * @param {Object} cellProperties Object containing the cell's properties.
 */
'beforeRenderer',

/**
 * Fired after finishing rendering the cell (after the renderer finishes).
 *
 * @event Hooks#afterRenderer
 * @since 0.11.0
 * @param {Element} TD Currently rendered cell's TD element.
 * @param {Number} row Visual row index.
 * @param {Number} col Visual column index.
 * @param {String|Number} prop Column property name or a column index, if datasource is an array of arrays.
 * @param {String} value Value of the rendered cell.
 * @param {Object} cellProperties Object containing the cell's properties.
 */
'afterRenderer',

/**
 * Fired after the horizontal scroll event.
 *
 * @event Hooks#afterScrollHorizontally
 * @since 0.11
 */
'afterScrollHorizontally',

/**
 * Fired after the vertical scroll event.
 *
 * @event Hooks#afterScrollVertically
 * @since 0.11
 */
'afterScrollVertically',

/**
 * Callback fired after one or more cells are selected (e.g. during mouse move).
 *
 * @event Hooks#afterSelection
 * @param {Number} r Selection start visual row index.
 * @param {Number} c Selection start visual column index.
 * @param {Number} r2 Selection end visual row index.
 * @param {Number} c2 Selection end visual column index.
 * @param {Object} preventScrolling Object with `value` property where its value change will be observed.
 *    * @example
 * ```js
 * handsontable({
 *   afterSelection: function (r, c, r2, c2, preventScrolling) {
 *     // setting if prevent scrolling after selection
 *
 *     preventScrolling.value = true;
 *   }
 * })
 * ```
 */
'afterSelection',

/**
 * Callback fired after one or more cells are selected. The `p` argument represents the source object property name instead of the column number.
 *
 * @event Hooks#afterSelectionByProp
 * @param {Number} r Selection start visual row index.
 * @param {String} p Selection start data source object property name.
 * @param {Number} r2 Selection end visual row index.
 * @param {String} p2 Selection end data source object property name.
 * @param {Object} preventScrolling Object with `value` property where its value change will be observed.
 *    * @example
 * ```js
 * handsontable({
 *   afterSelectionByProp: function (r, c, r2, c2, preventScrolling) {
 *     // setting if prevent scrolling after selection
 *
 *     preventScrolling.value = true;
 *   }
 * })
 * ```
 */
'afterSelectionByProp',

/**
 * Callback fired after one or more cells are selected (e.g. on mouse up).
 *
 * @event Hooks#afterSelectionEnd
 * @param {Number} r Selection start visual row index.
 * @param {Number} c Selection start visual column index.
 * @param {Number} r2 Selection end visual row index.
 * @param {Number} c2 Selection end visual column index.
 */
'afterSelectionEnd',

/**
 * Callback fired after one or more cells are selected (e.g. on mouse up). The `p` argument represents the data source object
 * property name instead of the column number.
 *
 * @event Hooks#afterSelectionEndByProp
 * @param {Number} r Selection start visual row index.
 * @param {String} p Selection start data source object property index.
 * @param {Number} r2 Selection end visual row index.
 * @param {String} p2 Selection end data source object property index.
 */
'afterSelectionEndByProp',

/**
 * Called after cell meta is changed.
 *
 * @event Hooks#afterSetCellMeta
 * @since 0.11.0
 * @param {Number} row Visual row index.
 * @param {Number} col Visual column index.
 * @param {String} key The updated meta key.
 * @param {*} value The updated meta value.
 */
'afterSetCellMeta',

/**
 * Called after cell meta is removed.
 *
 * @event Hooks#afterRemoveCellMeta
 * @since 0.33.1
 * @param {Number} row Visual row index.
 * @param {Number} col Visual column index.
 * @param {String} key The removed meta key.
 * @param {*} value Value which was under removed key of cell meta.
 */
'afterRemoveCellMeta',

/**
 * Called after cell data was changed.
 *
 * @event Hooks#afterSetDataAtCell
 * @since 0.28.0
 * @param {Array} changes An array of changes in format `[[row, col, oldValue, value], ...]`.
 * @param {String} [source] String that identifies source of hook call
 *                          ([list of all available sources]{@link http://docs.handsontable.com/tutorial-using-callbacks.html#page-source-definition}).
 */
'afterSetDataAtCell',

/**
 * Called after cell data was changed.
 *
 * @event Hooks#afterSetDataAtRowProp
 * @since 0.28.0
 * @param {Array} changes An array of changes in format `[[row, prop, oldValue, value], ...]`.
 * @param {String} [source] String that identifies source of hook call
 *                          ([list of all available sources]{@link http://docs.handsontable.com/tutorial-using-callbacks.html#page-source-definition}).
 */
'afterSetDataAtRowProp',

/**
 * Fired after calling the `updateSettings` method.
 *
 * @event Hooks#afterUpdateSettings
 * @param {Object} settings New settings object.
 */
'afterUpdateSettings',

/**
 * @description
 * A plugin hook executed after validator function, only if validator function is defined.
 * Validation result is the first parameter. This can be used to determinate if validation passed successfully or not.
 *
 * __Returning false from the callback will mark the cell as invalid.__
 *
 * @event Hooks#afterValidate
 * @since 0.9.5
 * @param {Boolean} isValid `true` if valid, `false` if not.
 * @param {*} value The value in question.
 * @param {Number} row Row index.
 * @param {String|Number} prop Property name / column index.
 * @param {String} [source] String that identifies source of hook call
 *                          ([list of all available sources]{@link http://docs.handsontable.com/tutorial-using-callbacks.html#page-source-definition}).
 */
'afterValidate',

/**
 * Fired before populating the data in the autofill feature.
 *
 * @event Hooks#beforeAutofill
 * @param {Object} start Object containing information about first filled cell: `{row: 2, col: 0}`.
 * @param {Object} end Object containing information about last filled cell: `{row: 4, col: 1}`.
 * @param {Array} data 2D array containing information about fill pattern: `[["1', "Ted"], ["1', "John"]]`.
 */
'beforeAutofill',

/**
 * Fired before aligning the cell contents.
 *
 * @event Hooks#beforeCellAlignment
 * @param stateBefore
 * @param range
 * @param {String} type Type of the alignment - either `horizontal` or `vertical`
 * @param {String} alignmentClass String defining the alignment class added to the cell.
 * Possible values:
 * * `htLeft`,
 * * `htCenter`,
 * * `htRight`,
 * * `htJustify`
 * for horizontal alignment,
 *
 *
 * * `htTop`,
 * * `htMiddle`,
 * * `htBottom`
 * for vertical alignment.
 */
'beforeCellAlignment',

/**
 * Callback fired before one or more cells is changed. Its main purpose is to alter changes silently before input.
 *
 * @event Hooks#beforeChange
 * @param {Array} changes 2D array containing information about each of the edited cells.
 * @param {String} [source] String that identifies source of hook call
 *                          ([list of all available sources]{@link http://docs.handsontable.com/tutorial-using-callbacks.html#page-source-definition}).
 * @example
 * ```js
 * // To disregard a single change, set changes[i] to null or remove it from array using changes.splice(i, 1).
 * ...
 * new Handsontable(document.getElementById('example'), {
 *   beforeChange: function(changes, source) {
 *     // [[row, prop, oldVal, newVal], ...]
 *     changes[0] = null;
 *   }
 * });
 * ...
 *
 * // To alter a single change, overwrite the desired value to changes[i][3].
 * ...
 * new Handsontable(document.getElementById('example'), {
 *   beforeChange: function(changes, source) {
 *     // [[row, prop, oldVal, newVal], ...]
 *     changes[0][3] = 10;
 *   }
 * });
 * ...
 *
 * // To cancel all edit, return false from the callback or set array length to 0 (changes.length = 0).
 * ...
 * new Handsontable(document.getElementById('example'), {
 *   beforeChange: function(changes, source) {
 *     // [[row, prop, oldVal, newVal], ...]
 *     return false;
 *   }
 * });
 * ...
 * ```
 */
'beforeChange',

/**
 * Fired right before rendering the changes.
 *
 * @event Hooks#beforeChangeRender
 * @since 0.11
 * @param {Array} changes Array in form of [row, prop, oldValue, newValue].
 * @param {String} [source] String that identifies source of hook call
 *                          ([list of all available sources]{@link http://docs.handsontable.com/tutorial-using-callbacks.html#page-source-definition}).
 */
'beforeChangeRender',

/**
 * Fired before drawing the borders.
 *
 * @event Hooks#beforeDrawBorders
 * @param {Array} corners Array specifying the current selection borders.
 * @param {String} borderClassName Specifies the border class name.
 */
'beforeDrawBorders',

/**
 * Callback fired before getting cell settings.
 *
 * @event Hooks#beforeGetCellMeta
 * @param {Number} row Visual row index.
 * @param {Number} col Visual column index.
 * @param {Object} cellProperties Object containing the cell's properties.
 */
'beforeGetCellMeta',

/**
 * Called before cell meta is removed.
 *
 * @event Hooks#beforeRemoveCellMeta
 * @since 0.33.1
 * @param {Number} row Visual row index.
 * @param {Number} col Visual column index.
 * @param {String} key The removed meta key.
 * @param {*} value Value which is under removed key of cell meta.
 */
'beforeRemoveCellMeta',

/**
 * @description
 * Callback fired before Handsontable instance is initiated.
 *
 * @event Hooks#beforeInit
 */
'beforeInit',

/**
 * Callback fired before Walkontable instance is initiated.
 *
 * @since 0.11
 * @event Hooks#beforeInitWalkontable
 * @param {Object} walkontableConfig Walkontable configuration object.
 */
'beforeInitWalkontable',

/**
 * Callback fired before keydown event is handled. It can be used to overwrite default key bindings.
 * Caution - in your `beforeKeyDown` handler you need to call `event.stopImmediatePropagation()` to prevent default key behavior.
 *
 * @event Hooks#beforeKeyDown
 * @since 0.9.0
 * @param {Event} event Original DOM event.
 */
'beforeKeyDown',

/**
 * Fired after the user clicked a cell, but before all the calculations related with it.
 *
 * @event Hooks#beforeOnCellMouseDown
 * @param {Event} event The `mousedown` event object.
 * @param {CellCoords} coords Cell coords object containing the visual coordinates of the clicked cell.
 * @param {Element} TD TD element.
 */
'beforeOnCellMouseDown',

/**
 * Fired after the user moved cursor over a cell, but before all the calculations related with it.
 *
 * @event Hooks#beforeOnCellMouseOver
 * @param {Event} event The `mouseover` event object.
 * @param {CellCoords} coords CellCoords object containing the visual coordinates of the clicked cell.
 * @param {Element} TD TD element.
 * @param {Object} blockCalculations Contain keys 'row' and 'column' with boolean value.
 */
'beforeOnCellMouseOver',

/**
 * Fired after the user moved cursor out from a cell, but before all the calculations related with it.
 *
 * @event Hooks#beforeOnCellMouseOut
 * @since 0.31.1
 * @param {Event} event The `mouseout` event object.
 * @param {WalkontableCellCoords} coords WalkontableCellCoords object containing the visual coordinates of the leaved cell.
 * @param {Element} TD TD element.
 */
'beforeOnCellMouseOut',

/**
 * Callback is fired when one or more columns are about to be removed.
 *
 * @event Hooks#beforeRemoveCol
 * @param {Number} index Visual index of starter column.
 * @param {Number} amount Amount of columns to be removed.
 * @param {Array} [visualCols] Consists of visual indexes of processed columns.
 */
'beforeRemoveCol',

/**
 * Callback is fired when one or more rows are about to be removed.
 *
 * @event Hooks#beforeRemoveRow
 * @param {Number} index Visual index of starter column.
 * @param {Number} amount Amount of columns to be removed.
 * @param {Array} [visualRows] Consists of visual indexes of processed rows.
 */
'beforeRemoveRow',

/**
 * Callback fired before Handsontable table is rendered.
 *
 * @event Hooks#beforeRender
 * @param {Boolean} isForced If `true` rendering was triggered by a change of settings or data; or `false` if
 *                           rendering was triggered by scrolling or moving selection.
 */
'beforeRender',

/**
 * Callback fired before setting range is started.
 *
 * @event Hooks#beforeSetRangeStart
 * @param {Array} coords CellCoords array.
 */
'beforeSetRangeStart',

/**
 * Callback fired before setting range is ended.
 *
 * @event Hooks#beforeSetRangeEnd
 * @param {Array} coords CellCoords array.
 */
'beforeSetRangeEnd',

/**
 * Fired before the logic of handling a touch scroll, when user started scrolling on a touch-enabled device.
 *
 * @event Hooks#beforeTouchScroll
 */
'beforeTouchScroll',

/**
 * @description
 * A plugin hook executed before validator function, only if validator function is defined.
 * This can be used to manipulate the value of changed cell before it is applied to the validator function.
 *
 * __Notice:__ this will not affect values of changes. This will change value ONLY for validation!
 *
 * @event Hooks#beforeValidate
 * @since 0.9.5
 * @param {*} value Value of the cell.
 * @param {Number} row Row index.
 * @param {String|Number} prop Property name / column index.
 * @param {String} [source] String that identifies source of hook call
 *                          ([list of all available sources]{@link http://docs.handsontable.com/tutorial-using-callbacks.html#page-source-definition}).
 */
'beforeValidate',

/**
 * Callback fired before cell value is rendered into the DOM (through renderer function).
 *
 * @event Hooks#beforeValueRender
 * @since 0.29.0
 * @param {*} value Cell value to render.
 */
'beforeValueRender',

/**
 * Callback fired after Handsontable instance is constructed (via `new` operator).
 *
 * @event Hooks#construct
 * @since 0.16.1
 */
'construct',

/**
 * Callback fired after Handsontable instance is initiated but before table is rendered.
 *
 * @event Hooks#init
 * @since 0.16.1
 */
'init',

/**
 * Fired when a column index is about to be modified by a callback function.
 *
 * @event Hooks#modifyCol
 * @since 0.11
 * @param {Number} col Visual column index.
 */
'modifyCol',

/**
 * Fired when a column index is about to be de-modified by a callback function.
 *
 * @event Hooks#unmodifyCol
 * @since 0.23.0
 * @param {Number} col Physical column index.
 */
'unmodifyCol',

/**
 * Fired when a physical row index is about to be de-modified by a callback function.
 *
 * @event Hooks#unmodifyRow
 * @since 0.26.2
 * @param {Number} row Physical row index.
 */
'unmodifyRow',
/**
 * Fired when a column header index is about to be modified by a callback function.
 *
 * @event Hooks#modifyColHeader
 * @since 0.20.0
 * @param {Number} column Visual column header index.
 */
'modifyColHeader',

/**
 * Fired when a column width is about to be modified by a callback function.
 *
 * @event Hooks#modifyColWidth
 * @since 0.11
 * @param {Number} width Current column width.
 * @param {Number} col Column index.
 */
'modifyColWidth',

/**
 * Fired when a row index is about to be modified by a callback function.
 *
 * @event Hooks#modifyRow
 * @since 0.11
 * @param {Number} row Row index.
 */
'modifyRow',

/**
 * Fired when a row header index is about to be modified by a callback function.
 *
 * @event Hooks#modifyRowHeader
 * @since 0.20.0
 * @param {Number} row Row header index.
 */
'modifyRowHeader',

/**
 * Fired when a row height is about to be modified by a callback function.
 *
 * @event Hooks#modifyRowHeight
 * @since 0.11.0
 * @param {Number} height Row height.
 * @param {Number} row Row index.
 */
'modifyRowHeight',

/**
 * Fired when a data was retrieved or modified.
 *
 * @event Hooks#modifyData
 * @since 0.28.0
 * @param {Number} row Row height.
 * @param {Number} column Column index.
 * @param {Object} valueHolder Object which contains original value which can be modified by overwriting `.value` property.
 * @param {String} ioMode String which indicates for what operation hook is fired (`get` or `set`).
 */
'modifyData',

/**
 * Fired when a data was retrieved or modified.
 *
 * @event Hooks#modifyRowData
 * @since 0.28.0
 * @param {Number} row Physical row index.
 */
'modifyRowData',

/**
 * Fired after loading data using the Persistent State plugin.
 *
 * @event Hooks#persistentStateLoad
 * @param {String} key Key string.
 * @param {Object} valuePlaceholder Object containing the loaded data.
 */
'persistentStateLoad',

/**
 * Fired after resetting data using the Persistent State plugin.
 *
 * @event Hooks#persistentStateReset
 * @param {String} key Key string.
 */
'persistentStateReset',

/**
 * Fired after resetting data using the Persistent State plugin.
 *
 * @event Hooks#persistentStateSave
 * @param {String} key Key string.
 * @param {Mixed} value Value to save.
 */
'persistentStateSave',

/**
 * Fired before sorting the column. If you return `false` value then sorting will be not applied by
 * Handsontable (useful for server-side sorting).
 *
 * @event Hooks#beforeColumnSort
 * @param {Number} column Sorted visual column index.
 * @param {Boolean} order Soring order where:
 *  * `true` means ascending order,
 *  * `false` means descending order,
 *  * `undefined` means original order.
 */
'beforeColumnSort',

/**
 * Fired after sorting the column.
 *
 * @event Hooks#afterColumnSort
 * @param {Number} column Sorted visual column index.
 * @param {Boolean} order Soring order where:
 *  * `true` means ascending order
 *  * `false` means descending order
 *  * `undefined` means original order
 */
'afterColumnSort',

/**
 * @description
 * Fired after setting range of autofill.
 * Both arguments are provided in the following format:
 * ```js
 * [startRow, startColumn, endRow, endColumn]
 * ```
 *
 * @event Hooks#modifyAutofillRange
 * @param {Array} startArea Array of visual coordinates of the starting point for the drag-down operation.
 * @param {Array} entireArea Array of visual coordinates of the entire area of the drag-down operation.
 */
'modifyAutofillRange',

/**
 * Fired to allow modifying the copyable range with a callback function.
 *
 * @since 0.19.0
 * @event Hooks#modifyCopyableRange
 * @param {Array} copyableRanges Array of objects defining copyable cells.
 */
'modifyCopyableRange',

/**
 * Called before copying the values into clipboard and before clearing values of the selected cells.
 *
 * @event Hooks#beforeCut
 * @since 0.31.1
 * @param {Array} data An array of arrays which contains data to cut.
 * @param {Array} coords An array of objects with ranges of the visual indexes (`startRow`, `startCol`, `endRow`, `endCol`)
 *                       which will be cut out.
 * @returns {*} If returns `false` then operation of the cutting out is cancelled.
 *
 * @example
 * ```js
 * // To disregard a single row, remove it from array using data.splice(i, 1).
 * ...
 * new Handsontable(document.getElementById('example'), {
 *   beforeCut: function(data, coords) {
 *     // data -> [[1, 2, 3], [4, 5, 6]]
 *     data.splice(0, 1);
 *     // data -> [[4, 5, 6]]
 *     // coords -> [{startRow: 0, startCol: 0, endRow: 1, endCol: 2}]
 *   }
 * });
 * ...
 *
 * // To cancel cutting out, return false from the callback.
 * ...
 * new Handsontable(document.getElementById('example'), {
 *   beforeCut: function(data, coords) {
 *     return false;
 *   }
 * });
 * ...
 * ```
 */
'beforeCut',

/**
 * Fired after data are cutted out from the table.
 *
 * @event Hooks#afterCut
 * @since 0.31.1
 * @param {Array} data An array of arrays which contains the cutted out data.
 * @param {Array} coords An array of objects with ranges of the visual indexes (`startRow`, `startCol`, `endRow`, `endCol`)
 *                       which was cut out.
 */
'afterCut',

/**
 * Fired before values are copied into clipboard.
 *
 * @event Hooks#beforeCopy
 * @since 0.31.1
 * @param {Array} data An array of arrays which contains data to copied.
 * @param {Array} coords An array of objects with ranges of the visual indexes (`startRow`, `startCol`, `endRow`, `endCol`)
 *                       which will copied.
 * @returns {*} If returns `false` then copying is cancelled.
 *
 * @example
 * ```js
 * // To disregard a single row, remove it from array using data.splice(i, 1).
 * ...
 * new Handsontable(document.getElementById('example'), {
 *   beforeCopy: function(data, coords) {
 *     // data -> [[1, 2, 3], [4, 5, 6]]
 *     data.splice(0, 1);
 *     // data -> [[4, 5, 6]]
 *     // coords -> [{startRow: 0, startCol: 0, endRow: 1, endCol: 2}]
 *   }
 * });
 * ...
 *
 * // To cancel copying, return false from the callback.
 * ...
 * new Handsontable(document.getElementById('example'), {
 *   beforeCopy: function(data, coords) {
 *     return false;
 *   }
 * });
 * ...
 * ```
 */
'beforeCopy',

/**
 * Fired after data are pasted into table.
 *
 * @event Hooks#afterCopy
 * @since 0.31.1
 * @param {Array} data An array of arrays which contains the copied data.
 * @param {Array} coords An array of objects with ranges of the visual indexes (`startRow`, `startCol`, `endRow`, `endCol`)
 *                       which was copied.
 */
'afterCopy',

/**
 * Fired before values are pasted into table.
 *
 * @event Hooks#beforePaste
 * @since 0.31.1
 * @param {Array} data An array of arrays which contains data to paste.
 * @param {Array} coords An array of objects with ranges of the visual indexes (`startRow`, `startCol`, `endRow`, `endCol`)
 *                       that correspond to the previously selected area.
 * @returns {*} If returns `false` then pasting is cancelled.
 *
 * @example
 * ```js
 * // To disregard a single row, remove it from array using data.splice(i, 1).
 * ...
 * new Handsontable(document.getElementById('example'), {
 *   beforePaste: function(data, coords) {
 *     // data -> [[1, 2, 3], [4, 5, 6]]
 *     data.splice(0, 1);
 *     // data -> [[4, 5, 6]]
 *     // coords -> [{startRow: 0, startCol: 0, endRow: 1, endCol: 2}]
 *   }
 * });
 * ...
 *
 * // To cancel pasting, return false from the callback.
 * ...
 * new Handsontable(document.getElementById('example'), {
 *   beforePaste: function(data, coords) {
 *     return false;
 *   }
 * });
 * ...
 * ```
 */
'beforePaste',

/**
 * Fired after values are pasted into table.
 *
 * @event Hooks#afterePaste
 * @since 0.31.1
 * @param {Array} data An array of arrays which contains the pasted data.
 * @param {Array} coords An array of objects with ranges of the visual indexes (`startRow`, `startCol`, `endRow`, `endCol`)
 *                       that correspond to the previously selected area.
 */
'afterPaste',

/**
 * Fired before change order of the visual indexes.
 *
 * @event Hooks#beforeColumnMove
 * @param {Array} columns Array of visual column indexes to be moved.
 * @param {Number} target Visual column index being a target for moved columns.
 */
'beforeColumnMove',

/**
 * Fired after change order of the visual indexes.
 *
 * @event Hooks#afterColumnMove
 * @param {Array} columns Array of visual column indexes that were moved.
 * @param {Number} target Visual column index being a target for moved columns.
 */
'afterColumnMove',

/**
 * Fired before change order of the visual indexes.
 *
 * @event Hooks#beforeRowMove
 * @param {Array} rows Array of visual row indexes to be moved.
 * @param {Number} target Visual row index being a target for moved rows.
 */
'beforeRowMove',

/**
 * Fired after change order of the visual indexes.
 *
 * @event Hooks#afterRowMove
 * @param {Array} rows Array of visual row indexes that were moved.
 * @param {Number} target Visual row index being a target for moved rows.
 */
'afterRowMove',

/**
 * Fired before rendering the table with modified column sizes.
 *
 * @event Hooks#beforeColumnResize
 * @param {Number} currentColumn Visual index of the resized column.
 * @param {Number} newSize Calculated new column width.
 * @param {Boolean} isDoubleClick Flag that determines whether there was a double-click.
 * @returns {Number} Returns a new column size or `undefined`, if column size should be calculated automatically.
 */
'beforeColumnResize',

/**
 * Fired after rendering the table with modified column sizes.
 *
 * @event Hooks#afterColumnResize
 * @param {Number} currentColumn Visual index of the resized column.
 * @param {Number} newSize Calculated new column width.
 * @param {Boolean} isDoubleClick Flag that determines whether there was a double-click.
 */
'afterColumnResize',

/**
 * Fired before rendering the table with modified row sizes.
 *
 * @event Hooks#beforeRowResize
 * @param {Number} currentRow Visual index of the resized row.
 * @param {Number} newSize Calculated new row height.
 * @param {Boolean} isDoubleClick Flag that determines whether there was a double-click.
 * @returns {Number} Returns the new row size or `undefined` if row size should be calculated automatically.
 */
'beforeRowResize',

/**
 * Fired after rendering the table with modified row sizes.
 *
 * @event Hooks#afterRowResize
 * @param {Number} currentRow Visual index of the resized row.
 * @param {Number} newSize Calculated new row height.
 * @param {Boolean} isDoubleClick Flag that determines whether there was a double-click.
 */
'afterRowResize',

/**
 * Fired after getting the column header renderers.
 *
 * @event Hooks#afterGetColumnHeaderRenderers
 * @param {Array} array Array of the column header renderers.
 */
'afterGetColumnHeaderRenderers',

/**
 * Fired after getting the row header renderers.
 *
 * @event Hooks#afterGetRowHeaderRenderers
 * @param {Array} array Array of the row header renderers.
 */
'afterGetRowHeaderRenderers',

/**
 * Fired before applying stretched column width to column.
 *
 * @event Hooks#beforeStretchingColumnWidth
 * @param {Number} stretchedWidth Calculated width.
 * @param {Number} column Visual column index.
 * @returns {Number} Returns new width which will be applied to the column element.
 */
'beforeStretchingColumnWidth',

/**
 * Fired before applying [filtering]{@link http://docs.handsontable.com/pro/demo-filtering.html}.
 *
 * @pro
 * @event Hooks#beforeFilter
 * @param {Array} conditionsStack An array of objects with added formulas.
 * @returns {Boolean} If hook returns `false` value then filtering won't be applied on the UI side (server-side filtering).
 */
'beforeFilter',

/**
 * Fired after applying [filtering]{@link http://docs.handsontable.com/pro/demo-filtering.html}.
 *
 * @pro
 * @event Hooks#afterFilter
 * @param {Array} conditionsStack An array of objects with added formulas.
 */
'afterFilter',

/**
 * Used to modify the column header height.
 *
 * @event Hooks#modifyColumnHeaderHeight
 * @since 0.25.0
 * @param {Number} col Visual column index.
 */
'modifyColumnHeaderHeight',

/**
 * Fired before the undo action. Contains information about the action that is being undone.
 *
 * @event Hooks#beforeUndo
 * @since 0.26.2
 * @param {Object} action The action object. Contains information about the action being undone. The `actionType`
 * property of the object specifies the type of the action in a String format. (e.g. `'remove_row'`).
 */
'beforeUndo',

/**
 * Fired after the undo action. Contains information about the action that is being undone.
 *
 * @event Hooks#afterUndo
 * @since 0.26.2
 * @param {Object} action The action object. Contains information about the action being undone. The `actionType`
 * property of the object specifies the type of the action in a String format. (e.g. `'remove_row'`).
 */
'afterUndo',

/**
 * Fired before the redo action. Contains information about the action that is being redone.
 *
 * @event Hooks#beforeRedo
 * @since 0.26.2
 * @param {Object} action The action object. Contains information about the action being redone. The `actionType`
 * property of the object specifies the type of the action in a String format. (e.g. `'remove_row'`).
 */
'beforeRedo',

/**
 * Fired after the redo action. Contains information about the action that is being redone.
 *
 * @event Hooks#afterRedo
 * @since 0.26.2
 * @param {Object} action The action object. Contains information about the action being redone. The `actionType`
 * property of the object specifies the type of the action in a String format. (e.g. `'remove_row'`).
 */
'afterRedo',

/**
 * Used to modify the row header width.
 *
 * @event Hooks#modifyRowHeaderWidth
 * @param {Number} rowHeaderWidth Row header width.
 */
'modifyRowHeaderWidth',

/**
 * Fired from the `populateFromArray` method during the `autofill` process. Fired for each "autofilled" cell individually.
 *
 * @event Hooks#beforeAutofillInsidePopulate
 * @param {Object} index Object containing `row` and `col` properties, defining the number of rows/columns from the initial cell of the autofill.
 * @param {String} direction Declares the direction of the autofill. Possible values: `up`, `down`, `left`, `right`.
 * @param {Array} input Array of arrays. Contains an array of rows with data being used in the autofill.
 * @param {Array} deltas The deltas array passed to the `populateFromArray` method.
 */
'beforeAutofillInsidePopulate',

/**
 * Fired when the start of the selection is being modified. (e.g. moving the selection with the arrow keys).
 *
 * @event Hooks#modifyTransformStart
 * @param {CellCoords} delta Cell coords object declaring the delta of the new selection relative to the previous one.
 */
'modifyTransformStart',

/**
 * Fired when the end of the selection is being modified. (e.g. moving the selection with the arrow keys).
 *
 * @event Hooks#modifyTransformEnd
 * @param {CellCoords} delta Cell coords object declaring the delta of the new selection relative to the previous one.
 */
'modifyTransformEnd',

/**
 * Fired after the start of the selection is being modified. (e.g. moving the selection with the arrow keys).
 *
 * @event Hooks#afterModifyTransformStart
 * @param {CellCoords} coords Coords of the freshly selected cell.
 * @param {Number} rowTransformDir `-1` if trying to select a cell with a negative row index. `0` otherwise.
 * @param {Number} colTransformDir `-1` if trying to select a cell with a negative column index. `0` otherwise.
 */
'afterModifyTransformStart',

/**
 * Fired after the end of the selection is being modified. (e.g. moving the selection with the arrow keys).
 *
 * @event Hooks#afterModifyTransformEnd
 * @param {CellCoords} coords Visual coords of the freshly selected cell.
 * @param {Number} rowTransformDir `-1` if trying to select a cell with a negative row index. `0` otherwise.
 * @param {Number} colTransformDir `-1` if trying to select a cell with a negative column index. `0` otherwise.
 */
'afterModifyTransformEnd',

/**
 * Fired inside the `viewportRowCalculatorOverride` method. Allows modifying the row calculator parameters.
 *
 * @event Hooks#afterViewportRowCalculatorOverride
 * @param {Object} calc The row calculator.
 */
'afterViewportRowCalculatorOverride',

/**
 * Fired inside the `viewportColumnCalculatorOverride` method. Allows modifying the row calculator parameters.
 *
 * @event Hooks#afterViewportColumnCalculatorOverride
 * @param {Object} calc The row calculator.
 */
'afterViewportColumnCalculatorOverride',

/**
 * Fired after initializing all the plugins.
 *
 * @event Hooks#afterPluginsInitialized
 */
'afterPluginsInitialized',

/**
 * Used when saving/loading the manual row heights state.
 *
 * @event Hooks#manualRowHeights
 * @param {Array} state The current manual row heights state.
 */
'manualRowHeights',

/**
 * Used to skip the length cache calculation for a defined period of time.
 *
 * @event Hooks#skipLengthCache
 * @param {Number} delay The delay in milliseconds.
 */
'skipLengthCache',

/**
 * Fired after trimming rows in the TrimRows plugin.
 *
 * @pro
 * @event Hooks#afterTrimRow
 * @param {Array} rows Physical indexes of trimmed rows.
 */
'afterTrimRow',

/**
 * Fired after untrimming rows in the TrimRows plugin.
 *
 * @pro
 * @event Hooks#afterUntrimRow
 * @param {Array} rows Physical indexes of untrimmed rows.
 */
'afterUntrimRow',

/**
 * Fired after opening the dropdown menu.
 *
 * @pro
 * @event Hooks#afterDropdownMenuShow
 * @param {DropdownMenu} instance The DropdownMenu instance.
 */
'afterDropdownMenuShow',

/**
 * Fired after hiding the dropdown menu.
 *
 * @pro
 * @event Hooks#afterDropdownMenuHide
 * @param {DropdownMenu} instance The DropdownMenu instance.
 */
'afterDropdownMenuHide',

/**
 * Used to check whether the provided row index is hidden.
 *
 * @pro
 * @event Hooks#hiddenRow
 * @param {Number} row The visual row index in question.
 */
'hiddenRow',

/**
 * Used to check whether the provided column index is hidden.
 *
 * @pro
 * @event Hooks#hiddenColumn
 * @param {Number} column The visual column index in question.
 */
'hiddenColumn',

/**
 * Fired before adding a children to the NestedRows structure.
 *
 * @pro
 * @event Hooks#beforeAddChild
 * @param {Object} parent The parent object.
 * @param {Object|undefined} element The element added as a child. If `undefined`, a blank child was added.
 * @param {Number|undefined} index The index within the parent where the new child was added. If `undefined`, the element was added as the last child.
 */
'beforeAddChild',

/**
 * Fired after adding a children to the NestedRows structure.
 *
 * @pro
 * @event Hooks#afterAddChild
 * @param {Object} parent The parent object.
 * @param {Object|undefined} element The element added as a child. If `undefined`, a blank child was added.
 * @param {Number|undefined} index The index within the parent where the new child was added. If `undefined`, the element was added as the last child.
 */
'afterAddChild',

/**
 * Fired before detaching a child from its parent in the NestedRows plugin.
 *
 * @pro
 * @event Hooks#beforeDetachChild
 * @param {Object} parent An object representing the parent from which the element is to be detached.
 * @param {Object} element The detached element.
 */
'beforeDetachChild',

/**
 * Fired after detaching a child from its parent in the NestedRows plugin.
 *
 * @pro
 * @event Hooks#afterDetachChild
 * @param {Object} parent An object representing the parent from which the element was detached.
 * @param {Object} element The detached element.
 */
'afterDetachChild',

/**
 * Fired after the editor is opened and rendered.
 *
 * @event Hooks#afterBeginEditing
 * @param {Number} row Row index of the edited cell.
 * @param {Number} column Column index of the edited cell.
 */
'afterBeginEditing'];

var Hooks = function () {
  _createClass(Hooks, null, [{
    key: 'getSingleton',
    value: function getSingleton() {
      return globalSingleton;
    }

    /**
     *
     */

  }]);

  function Hooks() {
    _classCallCheck(this, Hooks);

    this.globalBucket = this.createEmptyBucket();
  }

  /**
   * Returns a new object with empty handlers related to every registered hook name.
   *
   * @returns {Object} The empty bucket object.
   *
   * @example
   * ```js
   * Handsontable.hooks.createEmptyBucket();
   * // Results:
   * {
   * ...
   * afterCreateCol: [],
   * afterCreateRow: [],
   * beforeInit: [],
   * ...
   * }
   * ```
   */


  _createClass(Hooks, [{
    key: 'createEmptyBucket',
    value: function createEmptyBucket() {
      var bucket = Object.create(null);

      // eslint-disable-next-line no-return-assign
      (0, _array.arrayEach)(REGISTERED_HOOKS, function (hook) {
        return bucket[hook] = [];
      });

      return bucket;
    }

    /**
     * Get hook bucket based on the context of the object or if argument is `undefined`, get the global hook bucket.
     *
     * @param {Object} [context=null] A Handsontable instance.
     * @returns {Object} Returns a global or Handsontable instance bucket.
     */

  }, {
    key: 'getBucket',
    value: function getBucket() {
      var context = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;

      if (context) {
        if (!context.pluginHookBucket) {
          context.pluginHookBucket = this.createEmptyBucket();
        }

        return context.pluginHookBucket;
      }

      return this.globalBucket;
    }

    /**
     * Adds a listener (globally or locally) to a specified hook name.
     * If the `context` parameter is provided, the hook will be added only to the instance it references.
     * Otherwise, the callback will be used everytime the hook fires on any Handsontable instance.
     * You can provide an array of callback functions as the `callback` argument, this way they will all be fired
     * once the hook is triggered.
     *
     * @see Core#addHook
     * @param {String} key Hook name.
     * @param {Function|Array} callback Callback function or an array of functions.
     * @param {Object} [context=null] The context for the hook callback to be added - a Handsontable instance or leave empty.
     * @returns {Hooks} Instance of Hooks.
     *
     * @example
     * ```js
     * // single callback, added locally
     * Handsontable.hooks.add('beforeInit', myCallback, hotInstance);
     *
     * // single callback, added globally
     * Handsontable.hooks.add('beforeInit', myCallback);
     *
     * // multiple callbacks, added locally
     * Handsontable.hooks.add('beforeInit', [myCallback, anotherCallback], hotInstance);
     *
     * // multiple callbacks, added globally
     * Handsontable.hooks.add('beforeInit', [myCallback, anotherCallback]);
     * ```
     */

  }, {
    key: 'add',
    value: function add(key, callback) {
      var _this = this;

      var context = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null;

      if (Array.isArray(callback)) {
        (0, _array.arrayEach)(callback, function (c) {
          return _this.add(key, c, context);
        });
      } else {
        var bucket = this.getBucket(context);

        if (typeof bucket[key] === 'undefined') {
          this.register(key);
          bucket[key] = [];
        }
        callback.skip = false;

        if (bucket[key].indexOf(callback) === -1) {
          // only add a hook if it has not already been added (adding the same hook twice is now silently ignored)
          var foundInitialHook = false;

          if (callback.initialHook) {
            (0, _array.arrayEach)(bucket[key], function (cb, i) {
              if (cb.initialHook) {
                bucket[key][i] = callback;
                foundInitialHook = true;

                return false;
              }
            });
          }

          if (!foundInitialHook) {
            bucket[key].push(callback);
          }
        }
      }

      return this;
    }

    /**
     * Adds a listener to a specified hook. After the hook runs this listener will be automatically removed from the bucket.
     *
     * @see Core#addHookOnce
     * @param {String} key Hook/Event name.
     * @param {Function|Array} callback Callback function.
     * @param {Object} [context=null] A Handsontable instance.
     *
     * @example
     * ```js
     * Handsontable.hooks.once('beforeInit', myCallback, hotInstance);
     * ```
     */

  }, {
    key: 'once',
    value: function once(key, callback) {
      var _this2 = this;

      var context = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null;

      if (Array.isArray(callback)) {
        (0, _array.arrayEach)(callback, function (c) {
          return _this2.once(key, c, context);
        });
      } else {
        callback.runOnce = true;
        this.add(key, callback, context);
      }
    }

    /**
     * Removes a listener from a hook with a given name. If the `context` argument is provided, it removes a listener from a local hook assigned to the given Handsontable instance.
     *
     * @see Core#removeHook
     * @param {String} key Hook/Event name.
     * @param {Function} callback Callback function (needs the be the function that was previously added to the hook).
     * @param {Object} [context=null] Handsontable instance.
     * @return {Boolean} Returns `true` if hook was removed, `false` otherwise.
     *
     * @example
     * ```js
     * Handsontable.hooks.remove('beforeInit', myCallback);
     * ```
     */

  }, {
    key: 'remove',
    value: function remove(key, callback) {
      var context = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null;

      var bucket = this.getBucket(context);

      if (typeof bucket[key] !== 'undefined') {
        if (bucket[key].indexOf(callback) >= 0) {
          callback.skip = true;

          return true;
        }
      }

      return false;
    }

    /**
     * Checks whether there are any registered listeners for the provided hook name.
     * If the `context` parameter is provided, it only checks for listeners assigned to the given Handsontable instance.
     *
     * @param {String} key Hook name.
     * @param {Object} [context=null] A Handsontable instance.
     * @returns {Boolean} `true` for success, `false` otherwise.
     */

  }, {
    key: 'has',
    value: function has(key) {
      var context = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;

      var bucket = this.getBucket(context);

      return !!(bucket[key] !== void 0 && bucket[key].length);
    }

    /**
     * Runs all local and global callbacks assigned to the hook identified by the `key` parameter.
     * It returns either a return value from the last called callback or the first parameter (`p1`) passed to the `run` function.
     *
     * @see Core#runHooks
     * @param {Object} context Handsontable instance.
     * @param {String} key Hook/Event name.
     * @param {*} [p1] Parameter to be passed as an argument to the callback function.
     * @param {*} [p2] Parameter to be passed as an argument to the callback function.
     * @param {*} [p3] Parameter to be passed as an argument to the callback function.
     * @param {*} [p4] Parameter to be passed as an argument to the callback function.
     * @param {*} [p5] Parameter to be passed as an argument to the callback function.
     * @param {*} [p6] Parameter to be passed as an argument to the callback function.
     * @returns {*} Either a return value from the last called callback or `p1`.
     *
     * @example
     * ```js
     * Handsontable.hooks.run(hot, 'beforeInit');
     * ```
     */

  }, {
    key: 'run',
    value: function run(context, key, p1, p2, p3, p4, p5, p6) {
      {
        var globalHandlers = this.globalBucket[key];
        var index = -1;
        var length = globalHandlers ? globalHandlers.length : 0;

        if (length) {
          // Do not optimise this loop with arrayEach or arrow function! If you do You'll decrease perf because of GC.
          while (++index < length) {
            if (!globalHandlers[index] || globalHandlers[index].skip) {
              /* eslint-disable no-continue */
              continue;
            }
            // performance considerations - http://jsperf.com/call-vs-apply-for-a-plugin-architecture
            var res = globalHandlers[index].call(context, p1, p2, p3, p4, p5, p6);

            if (res !== void 0) {
              p1 = res;
            }
            if (globalHandlers[index] && globalHandlers[index].runOnce) {
              this.remove(key, globalHandlers[index]);
            }
          }
        }
      }
      {
        var localHandlers = this.getBucket(context)[key];
        var _index = -1;
        var _length = localHandlers ? localHandlers.length : 0;

        if (_length) {
          // Do not optimise this loop with arrayEach or arrow function! If you do You'll decrease perf because of GC.
          while (++_index < _length) {
            if (!localHandlers[_index] || localHandlers[_index].skip) {
              /* eslint-disable no-continue */
              continue;
            }
            // performance considerations - http://jsperf.com/call-vs-apply-for-a-plugin-architecture
            var _res = localHandlers[_index].call(context, p1, p2, p3, p4, p5, p6);

            if (_res !== void 0) {
              p1 = _res;
            }
            if (localHandlers[_index] && localHandlers[_index].runOnce) {
              this.remove(key, localHandlers[_index], context);
            }
          }
        }
      }

      return p1;
    }

    /**
     * Destroy all listeners connected to the context. If no context is provided, the global listeners will be destroyed.
     *
     * @param {Object} [context=null] A Handsontable instance.
     * @example
     * ```js
     * // destroy the global listeners
     * Handsontable.hooks.destroy();
     *
     * // destroy the local listeners
     * Handsontable.hooks.destroy(hotInstance);
     * ```
     */

  }, {
    key: 'destroy',
    value: function destroy() {
      var context = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;

      // eslint-disable-next-line no-return-assign
      (0, _object.objectEach)(this.getBucket(context), function (value, key, bucket) {
        return bucket[key].length = 0;
      });
    }

    /**
     * Registers a hook name (adds it to the list of the known hook names). Used by plugins.
     * It is not necessary to call register, but if you use it, your plugin hook will be used returned by
     * the `getRegistered` method. (which itself is used in the demo http://docs.handsontable.com/tutorial-callbacks.html).
     *
     * @param key {String} The hook name.
     *
     * @example
     * ```js
     * Handsontable.hooks.register('myHook');
     * ```
     */

  }, {
    key: 'register',
    value: function register(key) {
      if (!this.isRegistered(key)) {
        REGISTERED_HOOKS.push(key);
      }
    }

    /**
     * Deregisters a hook name (removes it from the list of known hook names).
     *
     * @param key {String} Hook name.
     *
     * @example
     * ```js
     * Handsontable.hooks.deregister('myHook');
     * ```
     */

  }, {
    key: 'deregister',
    value: function deregister(key) {
      if (this.isRegistered(key)) {
        REGISTERED_HOOKS.splice(REGISTERED_HOOKS.indexOf(key), 1);
      }
    }

    /**
     * Returns a boolean depending on if a hook by such name has been registered.
     *
     * @param key {String} Hook name.
     * @returns {Boolean} `true` for success, `false` otherwise.
     *
     * @example
     * ```js
     * Handsontable.hooks.isRegistered('beforeInit');
     *
     * // Results:
     * true
     * ```
     */

  }, {
    key: 'isRegistered',
    value: function isRegistered(key) {
      return REGISTERED_HOOKS.indexOf(key) >= 0;
    }

    /**
     * Returns an array of registered hooks.
     *
     * @returns {Array} An array of registered hooks.
     *
     * @example
     * ```js
     * Handsontable.hooks.getRegistered();
     *
     * // Results:
     * [
     * ...
     *   'beforeInit',
     *   'beforeRender',
     *   'beforeSetRangeEnd',
     *   'beforeDrawBorders',
     *   'beforeChange',
     * ...
     * ]
     * ```
     */

  }, {
    key: 'getRegistered',
    value: function getRegistered() {
      return REGISTERED_HOOKS;
    }
  }]);

  return Hooks;
}();

var globalSingleton = new Hooks();

exports.default = Hooks;

/***/ }),
/* 12 */
/***/ (function(module, exports) {

module.exports = function (it) {
  return typeof it === 'object' ? it !== null : typeof it === 'function';
};


/***/ }),
/* 13 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


exports.__esModule = true;
exports.getRegisteredEditors = exports.getRegisteredEditorNames = exports.hasEditor = exports.getEditorInstance = exports.getEditor = exports.registerEditor = undefined;
exports.RegisteredEditor = RegisteredEditor;
exports._getEditorInstance = _getEditorInstance;

var _staticRegister2 = __webpack_require__(53);

var _staticRegister3 = _interopRequireDefault(_staticRegister2);

var _pluginHooks = __webpack_require__(11);

var _pluginHooks2 = _interopRequireDefault(_pluginHooks);

var _baseEditor = __webpack_require__(36);

var _baseEditor2 = _interopRequireDefault(_baseEditor);

var _autocompleteEditor = __webpack_require__(263);

var _autocompleteEditor2 = _interopRequireDefault(_autocompleteEditor);

var _checkboxEditor = __webpack_require__(324);

var _checkboxEditor2 = _interopRequireDefault(_checkboxEditor);

var _dateEditor = __webpack_require__(325);

var _dateEditor2 = _interopRequireDefault(_dateEditor);

var _dropdownEditor = __webpack_require__(326);

var _dropdownEditor2 = _interopRequireDefault(_dropdownEditor);

var _handsontableEditor = __webpack_require__(264);

var _handsontableEditor2 = _interopRequireDefault(_handsontableEditor);

var _mobileTextEditor = __webpack_require__(327);

var _mobileTextEditor2 = _interopRequireDefault(_mobileTextEditor);

var _numericEditor = __webpack_require__(328);

var _numericEditor2 = _interopRequireDefault(_numericEditor);

var _passwordEditor = __webpack_require__(329);

var _passwordEditor2 = _interopRequireDefault(_passwordEditor);

var _selectEditor = __webpack_require__(330);

var _selectEditor2 = _interopRequireDefault(_selectEditor);

var _textEditor = __webpack_require__(44);

var _textEditor2 = _interopRequireDefault(_textEditor);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

var registeredEditorClasses = new WeakMap(); /**
                                              * Utility to register editors and common namespace for keeping reference to all editor classes
                                              */

var _staticRegister = (0, _staticRegister3.default)('editors'),
    register = _staticRegister.register,
    getItem = _staticRegister.getItem,
    hasItem = _staticRegister.hasItem,
    getNames = _staticRegister.getNames,
    getValues = _staticRegister.getValues;

_register('base', _baseEditor2.default);
_register('autocomplete', _autocompleteEditor2.default);
_register('checkbox', _checkboxEditor2.default);
_register('date', _dateEditor2.default);
_register('dropdown', _dropdownEditor2.default);
_register('handsontable', _handsontableEditor2.default);
_register('mobile', _mobileTextEditor2.default);
_register('numeric', _numericEditor2.default);
_register('password', _passwordEditor2.default);
_register('select', _selectEditor2.default);
_register('text', _textEditor2.default);

function RegisteredEditor(editorClass) {
  var instances = {};
  var Clazz = editorClass;

  this.getConstructor = function () {
    return editorClass;
  };

  this.getInstance = function (hotInstance) {
    if (!(hotInstance.guid in instances)) {
      instances[hotInstance.guid] = new Clazz(hotInstance);
    }

    return instances[hotInstance.guid];
  };

  _pluginHooks2.default.getSingleton().add('afterDestroy', function () {
    instances = {};
  });
}

/**
 * Returns instance (singleton) of editor class.
 *
 * @param {String} name Name of an editor under which it has been stored.
 * @param {Object} hotInstance Instance of Handsontable.
 * @returns {Function} Returns instance of editor.
 */
function _getEditorInstance(name, hotInstance) {
  var editor = void 0;

  if (typeof name === 'function') {
    if (!registeredEditorClasses.get(name)) {
      _register(null, name);
    }
    editor = registeredEditorClasses.get(name);
  } else if (typeof name === 'string') {
    editor = getItem(name);
  } else {
    throw Error('Only strings and functions can be passed as "editor" parameter');
  }

  if (!editor) {
    throw Error('No editor registered under name "' + name + '"');
  }

  return editor.getInstance(hotInstance);
}

/**
 * Retrieve editor class.
 *
 * @param {String} name Editor identification.
 * @returns {Function} Returns editor class.
 */
function _getItem(name) {
  if (!hasItem(name)) {
    throw Error('No registered editor found under "' + name + '" name');
  }

  return getItem(name).getConstructor();
}

/**
 * Register editor class under specified name.
 *
 * @param {String} name Editor identification.
 * @param {Function} editorClass Editor class.
 */
function _register(name, editorClass) {
  var editorWrapper = new RegisteredEditor(editorClass);

  if (typeof name === 'string') {
    register(name, editorWrapper);
  }
  registeredEditorClasses.set(editorClass, editorWrapper);
}

exports.registerEditor = _register;
exports.getEditor = _getItem;
exports.getEditorInstance = _getEditorInstance;
exports.hasEditor = hasItem;
exports.getRegisteredEditorNames = getNames;
exports.getRegisteredEditors = getValues;

/***/ }),
/* 14 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


exports.__esModule = true;
exports.Viewport = exports.TableRenderer = exports.Table = exports.Settings = exports.Selection = exports.Scroll = exports.Overlays = exports.Event = exports.Core = exports.default = exports.Border = exports.TopLeftCornerOverlay = exports.TopOverlay = exports.LeftOverlay = exports.DebugOverlay = exports.RowFilter = exports.ColumnFilter = exports.CellRange = exports.CellCoords = exports.ViewportRowsCalculator = exports.ViewportColumnsCalculator = undefined;

__webpack_require__(98);

__webpack_require__(115);

__webpack_require__(124);

__webpack_require__(125);

__webpack_require__(109);

__webpack_require__(123);

__webpack_require__(106);

__webpack_require__(107);

__webpack_require__(108);

__webpack_require__(97);

__webpack_require__(120);

__webpack_require__(118);

__webpack_require__(116);

__webpack_require__(121);

__webpack_require__(122);

__webpack_require__(117);

__webpack_require__(119);

__webpack_require__(110);

__webpack_require__(111);

__webpack_require__(112);

__webpack_require__(114);

__webpack_require__(113);

__webpack_require__(95);

__webpack_require__(96);

__webpack_require__(91);

__webpack_require__(94);

__webpack_require__(93);

__webpack_require__(92);

__webpack_require__(70);

__webpack_require__(100);

__webpack_require__(101);

__webpack_require__(103);

__webpack_require__(102);

__webpack_require__(99);

__webpack_require__(105);

__webpack_require__(104);

__webpack_require__(126);

__webpack_require__(129);

__webpack_require__(127);

__webpack_require__(128);

__webpack_require__(131);

__webpack_require__(130);

__webpack_require__(133);

__webpack_require__(132);

var _viewportColumns = __webpack_require__(251);

var _viewportColumns2 = _interopRequireDefault(_viewportColumns);

var _viewportRows = __webpack_require__(252);

var _viewportRows2 = _interopRequireDefault(_viewportRows);

var _coords = __webpack_require__(43);

var _coords2 = _interopRequireDefault(_coords);

var _range = __webpack_require__(71);

var _range2 = _interopRequireDefault(_range);

var _column = __webpack_require__(255);

var _column2 = _interopRequireDefault(_column);

var _row = __webpack_require__(256);

var _row2 = _interopRequireDefault(_row);

var _debug = __webpack_require__(307);

var _debug2 = _interopRequireDefault(_debug);

var _left = __webpack_require__(308);

var _left2 = _interopRequireDefault(_left);

var _top = __webpack_require__(309);

var _top2 = _interopRequireDefault(_top);

var _topLeftCorner = __webpack_require__(310);

var _topLeftCorner2 = _interopRequireDefault(_topLeftCorner);

var _border = __webpack_require__(250);

var _border2 = _interopRequireDefault(_border);

var _core = __webpack_require__(253);

var _core2 = _interopRequireDefault(_core);

var _event = __webpack_require__(254);

var _event2 = _interopRequireDefault(_event);

var _overlays = __webpack_require__(257);

var _overlays2 = _interopRequireDefault(_overlays);

var _scroll = __webpack_require__(258);

var _scroll2 = _interopRequireDefault(_scroll);

var _selection = __webpack_require__(311);

var _selection2 = _interopRequireDefault(_selection);

var _settings = __webpack_require__(259);

var _settings2 = _interopRequireDefault(_settings);

var _table = __webpack_require__(260);

var _table2 = _interopRequireDefault(_table);

var _tableRenderer = __webpack_require__(261);

var _tableRenderer2 = _interopRequireDefault(_tableRenderer);

var _viewport = __webpack_require__(262);

var _viewport2 = _interopRequireDefault(_viewport);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

exports.ViewportColumnsCalculator = _viewportColumns2.default;
exports.ViewportRowsCalculator = _viewportRows2.default;
exports.CellCoords = _coords2.default;
exports.CellRange = _range2.default;
exports.ColumnFilter = _column2.default;
exports.RowFilter = _row2.default;
exports.DebugOverlay = _debug2.default;
exports.LeftOverlay = _left2.default;
exports.TopOverlay = _top2.default;
exports.TopLeftCornerOverlay = _topLeftCorner2.default;
exports.Border = _border2.default;
exports.default = _core2.default;
exports.Core = _core2.default;
exports.Event = _event2.default;
exports.Overlays = _overlays2.default;
exports.Scroll = _scroll2.default;
exports.Selection = _selection2.default;
exports.Settings = _settings2.default;
exports.Table = _table2.default;
exports.TableRenderer = _tableRenderer2.default;
exports.Viewport = _viewport2.default;

/***/ }),
/* 15 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


exports.__esModule = true;
exports.KEY_CODES = undefined;
exports.isPrintableChar = isPrintableChar;
exports.isMetaKey = isMetaKey;
exports.isCtrlKey = isCtrlKey;
exports.isKey = isKey;

var _array = __webpack_require__(2);

var KEY_CODES = exports.KEY_CODES = {
  MOUSE_LEFT: 1,
  MOUSE_RIGHT: 3,
  MOUSE_MIDDLE: 2,
  BACKSPACE: 8,
  COMMA: 188,
  INSERT: 45,
  DELETE: 46,
  END: 35,
  ENTER: 13,
  ESCAPE: 27,
  CONTROL_LEFT: 91,
  COMMAND_LEFT: 17,
  COMMAND_RIGHT: 93,
  ALT: 18,
  HOME: 36,
  PAGE_DOWN: 34,
  PAGE_UP: 33,
  PERIOD: 190,
  SPACE: 32,
  SHIFT: 16,
  CAPS_LOCK: 20,
  TAB: 9,
  ARROW_RIGHT: 39,
  ARROW_LEFT: 37,
  ARROW_UP: 38,
  ARROW_DOWN: 40,
  F1: 112,
  F2: 113,
  F3: 114,
  F4: 115,
  F5: 116,
  F6: 117,
  F7: 118,
  F8: 119,
  F9: 120,
  F10: 121,
  F11: 122,
  F12: 123,
  A: 65,
  X: 88,
  C: 67,
  V: 86
};

/**
 * Returns true if keyCode represents a printable character.
 *
 * @param {Number} keyCode
 * @returns {Boolean}
 */
function isPrintableChar(keyCode) {
  return keyCode == 32 || // space
  keyCode >= 48 && keyCode <= 57 || // 0-9
  keyCode >= 96 && keyCode <= 111 || // numpad
  keyCode >= 186 && keyCode <= 192 || // ;=,-./`
  keyCode >= 219 && keyCode <= 222 || // []{}\|"'
  keyCode >= 226 || // special chars (229 for Asian chars)
  keyCode >= 65 && keyCode <= 90; // a-z
}

/**
 * @param {Number} keyCode
 * @returns {Boolean}
 */
function isMetaKey(keyCode) {
  var metaKeys = [KEY_CODES.ARROW_DOWN, KEY_CODES.ARROW_UP, KEY_CODES.ARROW_LEFT, KEY_CODES.ARROW_RIGHT, KEY_CODES.HOME, KEY_CODES.END, KEY_CODES.DELETE, KEY_CODES.BACKSPACE, KEY_CODES.F1, KEY_CODES.F2, KEY_CODES.F3, KEY_CODES.F4, KEY_CODES.F5, KEY_CODES.F6, KEY_CODES.F7, KEY_CODES.F8, KEY_CODES.F9, KEY_CODES.F10, KEY_CODES.F11, KEY_CODES.F12, KEY_CODES.TAB, KEY_CODES.PAGE_DOWN, KEY_CODES.PAGE_UP, KEY_CODES.ENTER, KEY_CODES.ESCAPE, KEY_CODES.SHIFT, KEY_CODES.CAPS_LOCK, KEY_CODES.ALT];

  return metaKeys.indexOf(keyCode) !== -1;
}

/**
 * @param {Number} keyCode
 * @returns {Boolean}
 */
function isCtrlKey(keyCode) {
  return [KEY_CODES.CONTROL_LEFT, 224, KEY_CODES.COMMAND_LEFT, KEY_CODES.COMMAND_RIGHT].indexOf(keyCode) !== -1;
}

/**
 * @param {Number} keyCode
 * @param {String} baseCode
 * @returns {Boolean}
 */
function isKey(keyCode, baseCode) {
  var keys = baseCode.split('|');
  var result = false;

  (0, _array.arrayEach)(keys, function (key) {
    if (keyCode === KEY_CODES[key]) {
      result = true;

      return false;
    }
  });

  return result;
}

/***/ }),
/* 16 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


exports.__esModule = true;

var _createClass = 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); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

var _object = __webpack_require__(3);

var _array = __webpack_require__(2);

var _recordTranslator = __webpack_require__(268);

var _plugins = __webpack_require__(9);

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

var privatePool = new WeakMap();
var initializedPlugins = null;

/**
 * @private
 */

var BasePlugin = function () {
  /**
   * @param {Object} hotInstance Handsontable instance.
   */
  function BasePlugin(hotInstance) {
    var _this = this;

    _classCallCheck(this, BasePlugin);

    /**
     * Handsontable instance.
     *
     * @type {Core}
     */
    (0, _object.defineGetter)(this, 'hot', hotInstance, {
      writable: false
    });
    (0, _object.defineGetter)(this, 't', (0, _recordTranslator.getTranslator)(hotInstance), {
      writable: false
    });

    privatePool.set(this, { hooks: {} });
    initializedPlugins = null;

    this.pluginName = null;
    this.pluginsInitializedCallbacks = [];
    this.isPluginsReady = false;
    this.enabled = false;
    this.initialized = false;

    this.hot.addHook('afterPluginsInitialized', function () {
      return _this.onAfterPluginsInitialized();
    });
    this.hot.addHook('afterUpdateSettings', function () {
      return _this.onUpdateSettings();
    });
    this.hot.addHook('beforeInit', function () {
      return _this.init();
    });
  }

  _createClass(BasePlugin, [{
    key: 'init',
    value: function init() {
      this.pluginName = (0, _plugins.getPluginName)(this.hot, this);

      if (this.isEnabled && this.isEnabled()) {
        this.enablePlugin();
      }
      if (!initializedPlugins) {
        initializedPlugins = (0, _plugins.getRegistredPluginNames)(this.hot);
      }
      if (initializedPlugins.indexOf(this.pluginName) >= 0) {
        initializedPlugins.splice(initializedPlugins.indexOf(this.pluginName), 1);
      }
      if (!initializedPlugins.length) {
        this.hot.runHooks('afterPluginsInitialized');
      }
      this.initialized = true;
    }

    /**
     * Enable plugin for this Handsontable instance.
     */

  }, {
    key: 'enablePlugin',
    value: function enablePlugin() {
      this.enabled = true;
    }

    /**
     * Disable plugin for this Handsontable instance.
     */

  }, {
    key: 'disablePlugin',
    value: function disablePlugin() {
      if (this.eventManager) {
        this.eventManager.clear();
      }
      this.clearHooks();
      this.enabled = false;
    }

    /**
     * Add listener to plugin hooks system.
     *
     * @param {String} name
     * @param {Function} callback
     */

  }, {
    key: 'addHook',
    value: function addHook(name, callback) {
      privatePool.get(this).hooks[name] = privatePool.get(this).hooks[name] || [];

      var hooks = privatePool.get(this).hooks[name];

      this.hot.addHook(name, callback);
      hooks.push(callback);
      privatePool.get(this).hooks[name] = hooks;
    }

    /**
     * Remove all hooks listeners by hook name.
     *
     * @param {String} name
     */

  }, {
    key: 'removeHooks',
    value: function removeHooks(name) {
      var _this2 = this;

      (0, _array.arrayEach)(privatePool.get(this).hooks[name] || [], function (callback) {
        _this2.hot.removeHook(name, callback);
      });
    }

    /**
     * Clear all hooks.
     */

  }, {
    key: 'clearHooks',
    value: function clearHooks() {
      var _this3 = this;

      var hooks = privatePool.get(this).hooks;

      (0, _object.objectEach)(hooks, function (callbacks, name) {
        return _this3.removeHooks(name);
      });
      hooks.length = 0;
    }

    /**
     * Register function which will be immediately called after all plugins initialized.
     *
     * @param {Function} callback
     */

  }, {
    key: 'callOnPluginsReady',
    value: function callOnPluginsReady(callback) {
      if (this.isPluginsReady) {
        callback();
      } else {
        this.pluginsInitializedCallbacks.push(callback);
      }
    }

    /**
     * On after plugins initialized listener.
     *
     * @private
     */

  }, {
    key: 'onAfterPluginsInitialized',
    value: function onAfterPluginsInitialized() {
      (0, _array.arrayEach)(this.pluginsInitializedCallbacks, function (callback) {
        return callback();
      });
      this.pluginsInitializedCallbacks.length = 0;
      this.isPluginsReady = true;
    }

    /**
     * On update settings listener.
     *
     * @private
     */

  }, {
    key: 'onUpdateSettings',
    value: function onUpdateSettings() {
      if (this.isEnabled) {
        if (this.enabled && !this.isEnabled()) {
          this.disablePlugin();
        }
        if (!this.enabled && this.isEnabled()) {
          this.enablePlugin();
        }
        if (this.enabled && this.isEnabled()) {
          this.updatePlugin();
        }
      }
    }

    /**
     * Updates the plugin to use the latest options you have specified.
     *
     * @private
     */

  }, {
    key: 'updatePlugin',
    value: function updatePlugin() {}

    /**
     * Destroy plugin.
     */

  }, {
    key: 'destroy',
    value: function destroy() {
      var _this4 = this;

      if (this.eventManager) {
        this.eventManager.destroy();
      }
      this.clearHooks();

      (0, _object.objectEach)(this, function (value, property) {
        if (property !== 'hot' && property !== 't') {
          _this4[property] = null;
        }
      });
      delete this.t;
      delete this.hot;
    }
  }]);

  return BasePlugin;
}();

exports.default = BasePlugin;

/***/ }),
/* 17 */
/***/ (function(module, exports, __webpack_require__) {

var isObject = __webpack_require__(12);
module.exports = function (it) {
  if (!isObject(it)) throw TypeError(it + ' is not an object!');
  return it;
};


/***/ }),
/* 18 */
/***/ (function(module, exports, __webpack_require__) {

var anObject = __webpack_require__(17);
var IE8_DOM_DEFINE = __webpack_require__(275);
var toPrimitive = __webpack_require__(87);
var dP = Object.defineProperty;

exports.f = __webpack_require__(20) ? Object.defineProperty : function defineProperty(O, P, Attributes) {
  anObject(O);
  P = toPrimitive(P, true);
  anObject(Attributes);
  if (IE8_DOM_DEFINE) try {
    return dP(O, P, Attributes);
  } catch (e) { /* empty */ }
  if ('get' in Attributes || 'set' in Attributes) throw TypeError('Accessors not supported!');
  if ('value' in Attributes) O[P] = Attributes.value;
  return O;
};


/***/ }),
/* 19 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


exports.__esModule = true;
exports.normalizeSelection = normalizeSelection;
exports.isSeparator = isSeparator;
exports.hasSubMenu = hasSubMenu;
exports.isDisabled = isDisabled;
exports.isSelectionDisabled = isSelectionDisabled;
exports.getValidSelection = getValidSelection;
exports.prepareVerticalAlignClass = prepareVerticalAlignClass;
exports.prepareHorizontalAlignClass = prepareHorizontalAlignClass;
exports.getAlignmentClasses = getAlignmentClasses;
exports.align = align;
exports.checkSelectionConsistency = checkSelectionConsistency;
exports.markLabelAsSelected = markLabelAsSelected;
exports.isItemHidden = isItemHidden;
exports.filterSeparators = filterSeparators;

var _array = __webpack_require__(2);

var _element = __webpack_require__(0);

var _separator = __webpack_require__(73);

function normalizeSelection(selRange) {
  return {
    start: selRange.getTopLeftCorner(),
    end: selRange.getBottomRightCorner()
  };
}

function isSeparator(cell) {
  return (0, _element.hasClass)(cell, 'htSeparator');
}

function hasSubMenu(cell) {
  return (0, _element.hasClass)(cell, 'htSubmenu');
}

function isDisabled(cell) {
  return (0, _element.hasClass)(cell, 'htDisabled');
}

function isSelectionDisabled(cell) {
  return (0, _element.hasClass)(cell, 'htSelectionDisabled');
}

function getValidSelection(hot) {
  var selected = hot.getSelected();

  if (!selected) {
    return null;
  }
  if (selected[0] < 0) {
    return null;
  }

  return selected;
}

function prepareVerticalAlignClass(className, alignment) {
  if (className.indexOf(alignment) != -1) {
    return className;
  }
  className = className.replace('htTop', '').replace('htMiddle', '').replace('htBottom', '').replace('  ', '');

  className += ' ' + alignment;

  return className;
}

function prepareHorizontalAlignClass(className, alignment) {
  if (className.indexOf(alignment) != -1) {
    return className;
  }
  className = className.replace('htLeft', '').replace('htCenter', '').replace('htRight', '').replace('htJustify', '').replace('  ', '');

  className += ' ' + alignment;

  return className;
}

function getAlignmentClasses(range, callback) {
  var classes = {};

  for (var row = range.from.row; row <= range.to.row; row++) {
    for (var col = range.from.col; col <= range.to.col; col++) {
      if (!classes[row]) {
        classes[row] = [];
      }
      classes[row][col] = callback(row, col);
    }
  }

  return classes;
}

function align(range, type, alignment, cellDescriptor, propertySetter) {
  if (range.from.row == range.to.row && range.from.col == range.to.col) {
    applyAlignClassName(range.from.row, range.from.col, type, alignment, cellDescriptor, propertySetter);
  } else {
    for (var row = range.from.row; row <= range.to.row; row++) {
      for (var col = range.from.col; col <= range.to.col; col++) {
        applyAlignClassName(row, col, type, alignment, cellDescriptor, propertySetter);
      }
    }
  }
}

function applyAlignClassName(row, col, type, alignment, cellDescriptor, propertySetter) {
  var cellMeta = cellDescriptor(row, col);
  var className = alignment;

  if (cellMeta.className) {
    if (type === 'vertical') {
      className = prepareVerticalAlignClass(cellMeta.className, alignment);
    } else {
      className = prepareHorizontalAlignClass(cellMeta.className, alignment);
    }
  }

  propertySetter(row, col, 'className', className);
}

function checkSelectionConsistency(range, comparator) {
  var result = false;

  if (range) {
    range.forAll(function (row, col) {
      if (comparator(row, col)) {
        result = true;

        return false;
      }
    });
  }

  return result;
}

function markLabelAsSelected(label) {
  // workaround for https://github.com/handsontable/handsontable/issues/1946
  return '<span class="selected">' + String.fromCharCode(10003) + '</span>' + label;
}

function isItemHidden(item, instance) {
  return !item.hidden || !(typeof item.hidden == 'function' && item.hidden.call(instance));
}

function shiftSeparators(items, separator) {
  var result = items.slice(0);

  for (var i = 0; i < result.length;) {
    if (result[i].name === separator) {
      result.shift();
    } else {
      break;
    }
  }
  return result;
}

function popSeparators(items, separator) {
  var result = items.slice(0);

  result.reverse();
  result = shiftSeparators(result, separator);
  result.reverse();

  return result;
}

function removeDuplicatedSeparators(items) {
  var result = [];

  (0, _array.arrayEach)(items, function (value, index) {
    if (index > 0) {
      if (result[result.length - 1].name !== value.name) {
        result.push(value);
      }
    } else {
      result.push(value);
    }
  });

  return result;
}

function filterSeparators(items) {
  var separator = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : _separator.KEY;

  var result = items.slice(0);

  result = shiftSeparators(result, separator);
  result = popSeparators(result, separator);
  result = removeDuplicatedSeparators(result);

  return result;
}

/***/ }),
/* 20 */
/***/ (function(module, exports, __webpack_require__) {

// Thank's IE8 for his funny defineProperty
module.exports = !__webpack_require__(25)(function () {
  return Object.defineProperty({}, 'a', { get: function () { return 7; } }).a != 7;
});


/***/ }),
/* 21 */
/***/ (function(module, exports, __webpack_require__) {

// 7.1.15 ToLength
var toInteger = __webpack_require__(64);
var min = Math.min;
module.exports = function (it) {
  return it > 0 ? min(toInteger(it), 0x1fffffffffffff) : 0; // pow(2, 53) - 1 == 9007199254740991
};


/***/ }),
/* 22 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


exports.__esModule = true;
exports.isIE8 = isIE8;
exports.isIE9 = isIE9;
exports.isSafari = isSafari;
exports.isChrome = isChrome;
exports.isMobileBrowser = isMobileBrowser;

var _isIE8 = !document.createTextNode('test').textContent;

function isIE8() {
  return _isIE8;
}

var _isIE9 = !!document.documentMode;

function isIE9() {
  return _isIE9;
}

var _isSafari = /Safari/.test(navigator.userAgent) && /Apple Computer/.test(navigator.vendor);

function isSafari() {
  return _isSafari;
}

var _isChrome = /Chrome/.test(navigator.userAgent) && /Google/.test(navigator.vendor);

function isChrome() {
  return _isChrome;
}

function isMobileBrowser(userAgent) {
  if (!userAgent) {
    userAgent = navigator.userAgent;
  }

  return (/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(userAgent)
  );
}

/***/ }),
/* 23 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


exports.__esModule = true;

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

var _templateObject = _taggedTemplateLiteral(['\n          Your license key of Handsontable Pro has expired.\u200C\u200C\u200C\u200C \n          Renew your maintenance plan at https://handsontable.com or downgrade to the previous version of the software.\n          '], ['\n          Your license key of Handsontable Pro has expired.\u200C\u200C\u200C\u200C\\x20\n          Renew your maintenance plan at https://handsontable.com or downgrade to the previous version of the software.\n          ']);

exports.stringify = stringify;
exports.isDefined = isDefined;
exports.isUndefined = isUndefined;
exports.isEmpty = isEmpty;
exports.isRegExp = isRegExp;
exports._injectProductInfo = _injectProductInfo;

var _element = __webpack_require__(0);

var _templateLiteralTag = __webpack_require__(331);

function _taggedTemplateLiteral(strings, raw) { return Object.freeze(Object.defineProperties(strings, { raw: { value: Object.freeze(raw) } })); }

/**
 * Converts any value to string.
 *
 * @param {*} value
 * @returns {String}
 */
function stringify(value) {
  var result = void 0;

  switch (typeof value === 'undefined' ? 'undefined' : _typeof(value)) {
    case 'string':
    case 'number':
      result = '' + value;
      break;

    case 'object':
      result = value === null ? '' : value.toString();
      break;
    case 'undefined':
      result = '';
      break;
    default:
      result = value.toString();
      break;
  }

  return result;
}

/**
 * Checks if given variable is defined.
 *
 * @param {*} variable Variable to check.
 * @returns {Boolean}
 */
function isDefined(variable) {
  return typeof variable !== 'undefined';
}

/**
 * Checks if given variable is undefined.
 *
 * @param {*} variable Variable to check.
 * @returns {Boolean}
 */
function isUndefined(variable) {
  return typeof variable === 'undefined';
}

/**
 * Check if given variable is null, empty string or undefined.
 *
 * @param {*} variable Variable to check.
 * @returns {Boolean}
 */
function isEmpty(variable) {
  return variable === null || variable === '' || isUndefined(variable);
}

/**
 * Check if given variable is a regular expression.
 *
 * @param {*} variable Variable to check.
 * @returns {Boolean}
 */
function isRegExp(variable) {
  return Object.prototype.toString.call(variable) === '[object RegExp]';
}

/* eslint-disable */
var _m = '\x6C\x65\x6E\x67\x74\x68';
var _hd = function _hd(v) {
  return parseInt(v, 16);
};
var _pi = function _pi(v) {
  return parseInt(v, 10);
};
var _ss = function _ss(v, s, l) {
  return v['\x73\x75\x62\x73\x74\x72'](s, l);
};
var _cp = function _cp(v) {
  return v['\x63\x6F\x64\x65\x50\x6F\x69\x6E\x74\x41\x74'](0) - 65;
};
var _norm = function _norm(v) {
  return v.replace(/\-/g, '');
};
var _extractTime = function _extractTime(v) {
  return _hd(_ss(_norm(v), _hd('12'), _cp('\x46'))) / (_hd(_ss(_norm(v), _cp('\x42'), ~~![][_m])) || 9);
};
var _ignored = function _ignored() {
  return typeof location !== 'undefined' && /^([a-z0-9\-]+\.)?\x68\x61\x6E\x64\x73\x6F\x6E\x74\x61\x62\x6C\x65\x2E\x63\x6F\x6D$/i.test(location.host);
};
var _notified = false;

function _injectProductInfo(key, element) {
  key = _norm(key || '');

  var warningMessage = '';
  var showDomMessage = true;
  var schemaValidity = _checkKeySchema(key);
  var ignored = _ignored();
  var trial = isEmpty(key) || key === 'trial';

  if (trial || schemaValidity) {
    if (schemaValidity) {
      var releaseTime = Math.floor(moment(undefined, 'DD/MM/YYYY').toDate().getTime() / 8.64e7);
      var keyGenTime = _extractTime(key);

      if (keyGenTime > 45000 || keyGenTime !== parseInt(keyGenTime, 10)) {
        warningMessage = 'The license key provided to Handsontable Pro is invalid. Make sure you pass it correctly.';
      }

      if (!warningMessage) {
        if (releaseTime > keyGenTime + 1) {
          warningMessage = (0, _templateLiteralTag.toSingleLine)(_templateObject);
        }
        showDomMessage = releaseTime > keyGenTime + 15;
      }
    } else {
      warningMessage = 'Evaluation version of Handsontable Pro. Not licensed for use in a production environment.';
    }
  } else {
    warningMessage = 'The license key provided to Handsontable Pro is invalid. Make sure you pass it correctly.';
  }
  if (ignored) {
    warningMessage = false;
    showDomMessage = false;
  }

  if (warningMessage && !_notified) {
    console[trial ? 'info' : 'warn'](warningMessage);
    _notified = true;
  }
  if (showDomMessage && element.parentNode) {
    var message = document.createElement('div');

    (0, _element.addClass)(message, 'display-license-info');
    message.appendChild(document.createTextNode('Evaluation version of Handsontable Pro.'));
    message.appendChild(document.createElement('br'));
    message.appendChild(document.createTextNode('Not licensed for production use.'));

    element.parentNode.insertBefore(message, element.nextSibling);
  }
}

function _checkKeySchema(v) {
  var z = [][_m];
  var p = z;

  if (v[_m] !== _cp('\x5A')) {
    return false;
  }

  for (var c = '', i = '\x42\x3C\x48\x34\x50\x2B'.split(''), j = _cp(i.shift()); j; j = _cp(i.shift() || 'A')) {
    --j < ''[_m] ? p = p | (_pi('' + _pi(_hd(c) + (_hd(_ss(v, Math.abs(j), 2)) + []).padStart(2, '0'))) % _cp('\xA2') || 2) >> 1 : c = _ss(v, j, !j ? 6 : i[_m] === 1 ? 9 : 8);
  }

  return p === z;
}
/* eslint-enable */

/***/ }),
/* 24 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


exports.__esModule = true;
exports.getRegisteredValidators = exports.getRegisteredValidatorNames = exports.hasValidator = exports.getValidator = exports.registerValidator = undefined;

var _staticRegister2 = __webpack_require__(53);

var _staticRegister3 = _interopRequireDefault(_staticRegister2);

var _autocompleteValidator = __webpack_require__(385);

var _autocompleteValidator2 = _interopRequireDefault(_autocompleteValidator);

var _dateValidator = __webpack_require__(386);

var _dateValidator2 = _interopRequireDefault(_dateValidator);

var _numericValidator = __webpack_require__(387);

var _numericValidator2 = _interopRequireDefault(_numericValidator);

var _timeValidator = __webpack_require__(388);

var _timeValidator2 = _interopRequireDefault(_timeValidator);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

var _staticRegister = (0, _staticRegister3.default)('validators'),
    register = _staticRegister.register,
    getItem = _staticRegister.getItem,
    hasItem = _staticRegister.hasItem,
    getNames = _staticRegister.getNames,
    getValues = _staticRegister.getValues;

register('autocomplete', _autocompleteValidator2.default);
register('date', _dateValidator2.default);
register('numeric', _numericValidator2.default);
register('time', _timeValidator2.default);

/**
 * Retrieve validator function.
 *
 * @param {String} name Validator identification.
 * @returns {Function} Returns validator function.
 */
function _getItem(name) {
  if (typeof name === 'function') {
    return name;
  }
  if (!hasItem(name)) {
    throw Error('No registered validator found under "' + name + '" name');
  }

  return getItem(name);
}

exports.registerValidator = register;
exports.getValidator = _getItem;
exports.hasValidator = hasItem;
exports.getRegisteredValidatorNames = getNames;
exports.getRegisteredValidators = getValues;

/***/ }),
/* 25 */
/***/ (function(module, exports) {

module.exports = function (exec) {
  try {
    return !!exec();
  } catch (e) {
    return true;
  }
};


/***/ }),
/* 26 */
/***/ (function(module, exports) {

var hasOwnProperty = {}.hasOwnProperty;
module.exports = function (it, key) {
  return hasOwnProperty.call(it, key);
};


/***/ }),
/* 27 */
/***/ (function(module, exports, __webpack_require__) {

// to indexed object, toObject with fallback for non-array-like ES3 strings
var IObject = __webpack_require__(78);
var defined = __webpack_require__(33);
module.exports = function (it) {
  return IObject(defined(it));
};


/***/ }),
/* 28 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


exports.__esModule = true;
exports.toUpperCaseFirst = toUpperCaseFirst;
exports.equalsIgnoreCase = equalsIgnoreCase;
exports.randomString = randomString;
exports.isPercentValue = isPercentValue;
exports.substitute = substitute;
exports.stripTags = stripTags;

var _mixed = __webpack_require__(23);

var _number = __webpack_require__(5);

/**
 * Convert string to upper case first letter.
 *
 * @param {String} string String to convert.
 * @returns {String}
 */
function toUpperCaseFirst(string) {
  return string[0].toUpperCase() + string.substr(1);
}

/**
 * Compare strings case insensitively.
 *
 * @param {...String} strings Strings to compare.
 * @returns {Boolean}
 */
function equalsIgnoreCase() {
  var unique = [];

  for (var _len = arguments.length, strings = Array(_len), _key = 0; _key < _len; _key++) {
    strings[_key] = arguments[_key];
  }

  var length = strings.length;

  while (length--) {
    var string = (0, _mixed.stringify)(strings[length]).toLowerCase();

    if (unique.indexOf(string) === -1) {
      unique.push(string);
    }
  }

  return unique.length === 1;
}

/**
 * Generates a random hex string. Used as namespace for Handsontable instance events.
 *
 * @return {String} Returns 16-long character random string (eq. `'92b1bfc74ec4'`).
 */
function randomString() {
  function s4() {
    return Math.floor((1 + Math.random()) * 0x10000).toString(16).substring(1);
  }

  return s4() + s4() + s4() + s4();
}

/**
 * Checks if value is valid percent.
 *
 * @param {String} value
 * @returns {Boolean}
 */
function isPercentValue(value) {
  return (/^([0-9][0-9]?%$)|(^100%$)/.test(value)
  );
}

/**
 * Substitute strings placed beetwen square brackets into value defined in `variables` object. String names defined in
 * square brackets must be the same as property name of `variables` object.
 *
 * @param {String} template Template string.
 * @param {Object} variables Object which contains all available values which can be injected into template.
 * @returns {String}
 */
function substitute(template) {
  var variables = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};

  return ('' + template).replace(/(?:\\)?\[([^[\]]+)]/g, function (match, name) {
    if (match.charAt(0) === '\\') {
      return match.substr(1, match.length - 1);
    }

    return variables[name] === void 0 ? '' : variables[name];
  });
}

var STRIP_TAGS_REGEX = /<\/?\w+\/?>|<\w+[\s|/][^>]*>/gi;

/**
 * Strip any HTML tag from the string.
 *
 * @param  {String} string String to cut HTML from.
 * @return {String}
 */
function stripTags(string) {
  string += '';

  return string.replace(STRIP_TAGS_REGEX, '');
}

/***/ }),
/* 29 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


exports.__esModule = true;

var _createClass = 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); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

var _element = __webpack_require__(0);

var _object = __webpack_require__(3);

var _array = __webpack_require__(2);

var _eventManager = __webpack_require__(4);

var _eventManager2 = _interopRequireDefault(_eventManager);

var _core = __webpack_require__(253);

var _core2 = _interopRequireDefault(_core);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

var registeredOverlays = {};

/**
 * Creates an overlay over the original Walkontable instance. The overlay renders the clone of the original Walkontable
 * and (optionally) implements behavior needed for native horizontal and vertical scrolling.
 *
 * @class Overlay
 */

var Overlay = function () {
  _createClass(Overlay, null, [{
    key: 'registerOverlay',


    /**
     * Register overlay class.
     *
     * @param {String} type Overlay type, one of the CLONE_TYPES value
     * @param {Overlay} overlayClass Overlay class extended from base overlay class {@link Overlay}
     */
    value: function registerOverlay(type, overlayClass) {
      if (Overlay.CLONE_TYPES.indexOf(type) === -1) {
        throw new Error('Unsupported overlay (' + type + ').');
      }
      registeredOverlays[type] = overlayClass;
    }

    /**
     * Create new instance of overlay type.
     *
     * @param {String} type Overlay type, one of the CLONE_TYPES value
     * @param {Walkontable} wot Walkontable instance
     */

  }, {
    key: 'createOverlay',
    value: function createOverlay(type, wot) {
      return new registeredOverlays[type](wot);
    }

    /**
     * Check if specified overlay was registered.
     *
     * @param {String} type Overlay type, one of the CLONE_TYPES value
     * @returns {Boolean}
     */

  }, {
    key: 'hasOverlay',
    value: function hasOverlay(type) {
      return registeredOverlays[type] !== void 0;
    }

    /**
     * Checks if overlay object (`overlay`) is instance of overlay type (`type`).
     *
     * @param {Overlay} overlay Overlay object
     * @param {String} type Overlay type, one of the CLONE_TYPES value
     * @returns {Boolean}
     */

  }, {
    key: 'isOverlayTypeOf',
    value: function isOverlayTypeOf(overlay, type) {
      if (!overlay || !registeredOverlays[type]) {
        return false;
      }

      return overlay instanceof registeredOverlays[type];
    }

    /**
     * @param {Walkontable} wotInstance
     */

  }, {
    key: 'CLONE_TOP',

    /**
     * @type {String}
     */
    get: function get() {
      return 'top';
    }

    /**
     * @type {String}
     */

  }, {
    key: 'CLONE_BOTTOM',
    get: function get() {
      return 'bottom';
    }

    /**
     * @type {String}
     */

  }, {
    key: 'CLONE_LEFT',
    get: function get() {
      return 'left';
    }

    /**
     * @type {String}
     */

  }, {
    key: 'CLONE_TOP_LEFT_CORNER',
    get: function get() {
      return 'top_left_corner';
    }

    /**
     * @type {String}
     */

  }, {
    key: 'CLONE_BOTTOM_LEFT_CORNER',
    get: function get() {
      return 'bottom_left_corner';
    }

    /**
     * @type {String}
     */

  }, {
    key: 'CLONE_DEBUG',
    get: function get() {
      return 'debug';
    }

    /**
     * List of all availables clone types
     *
     * @type {Array}
     */

  }, {
    key: 'CLONE_TYPES',
    get: function get() {
      return [Overlay.CLONE_TOP, Overlay.CLONE_BOTTOM, Overlay.CLONE_LEFT, Overlay.CLONE_TOP_LEFT_CORNER, Overlay.CLONE_BOTTOM_LEFT_CORNER, Overlay.CLONE_DEBUG];
    }
  }]);

  function Overlay(wotInstance) {
    _classCallCheck(this, Overlay);

    (0, _object.defineGetter)(this, 'wot', wotInstance, {
      writable: false
    });

    // legacy support, deprecated in the future
    this.instance = this.wot;

    this.type = '';
    this.mainTableScrollableElement = null;
    this.TABLE = this.wot.wtTable.TABLE;
    this.hider = this.wot.wtTable.hider;
    this.spreader = this.wot.wtTable.spreader;
    this.holder = this.wot.wtTable.holder;
    this.wtRootElement = this.wot.wtTable.wtRootElement;
    this.trimmingContainer = (0, _element.getTrimmingContainer)(this.hider.parentNode.parentNode);
    this.areElementSizesAdjusted = false;
    this.updateStateOfRendering();
  }

  /**
   * Update internal state of object with an information about the need of full rendering of the overlay.
   *
   * @returns {Boolean} Returns `true` if the state has changed since the last check.
   */


  _createClass(Overlay, [{
    key: 'updateStateOfRendering',
    value: function updateStateOfRendering() {
      var previousState = this.needFullRender;

      this.needFullRender = this.shouldBeRendered();

      var changed = previousState !== this.needFullRender;

      if (changed && !this.needFullRender) {
        this.reset();
      }

      return changed;
    }

    /**
     * Checks if overlay should be fully rendered
     *
     * @returns {Boolean}
     */

  }, {
    key: 'shouldBeRendered',
    value: function shouldBeRendered() {
      return true;
    }

    /**
     * Update the trimming container.
     */

  }, {
    key: 'updateTrimmingContainer',
    value: function updateTrimmingContainer() {
      this.trimmingContainer = (0, _element.getTrimmingContainer)(this.hider.parentNode.parentNode);
    }

    /**
     * Update the main scrollable element.
     */

  }, {
    key: 'updateMainScrollableElement',
    value: function updateMainScrollableElement() {
      this.mainTableScrollableElement = (0, _element.getScrollableElement)(this.wot.wtTable.TABLE);
    }

    /**
     * Make a clone of table for overlay
     *
     * @param {String} direction Can be `Overlay.CLONE_TOP`, `Overlay.CLONE_LEFT`,
     *                           `Overlay.CLONE_TOP_LEFT_CORNER`, `Overlay.CLONE_DEBUG`
     * @returns {Walkontable}
     */

  }, {
    key: 'makeClone',
    value: function makeClone(direction) {
      if (Overlay.CLONE_TYPES.indexOf(direction) === -1) {
        throw new Error('Clone type "' + direction + '" is not supported.');
      }
      var clone = document.createElement('DIV');
      var clonedTable = document.createElement('TABLE');

      clone.className = 'ht_clone_' + direction + ' handsontable';
      clone.style.position = 'absolute';
      clone.style.top = 0;
      clone.style.left = 0;
      clone.style.overflow = 'hidden';

      clonedTable.className = this.wot.wtTable.TABLE.className;
      clone.appendChild(clonedTable);

      this.type = direction;
      this.wot.wtTable.wtRootElement.parentNode.appendChild(clone);

      var preventOverflow = this.wot.getSetting('preventOverflow');

      if (preventOverflow === true || preventOverflow === 'horizontal' && this.type === Overlay.CLONE_TOP || preventOverflow === 'vertical' && this.type === Overlay.CLONE_LEFT) {
        this.mainTableScrollableElement = window;
      } else {
        this.mainTableScrollableElement = (0, _element.getScrollableElement)(this.wot.wtTable.TABLE);
      }

      return new _core2.default({
        cloneSource: this.wot,
        cloneOverlay: this,
        table: clonedTable
      });
    }

    /**
     * Refresh/Redraw overlay
     *
     * @param {Boolean} [fastDraw=false]
     */

  }, {
    key: 'refresh',
    value: function refresh() {
      var fastDraw = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;

      // When hot settings are changed we allow to refresh overlay once before blocking
      var nextCycleRenderFlag = this.shouldBeRendered();

      if (this.clone && (this.needFullRender || nextCycleRenderFlag)) {
        this.clone.draw(fastDraw);
      }
      this.needFullRender = nextCycleRenderFlag;
    }

    /**
     * Reset overlay styles to initial values.
     */

  }, {
    key: 'reset',
    value: function reset() {
      if (!this.clone) {
        return;
      }
      var holder = this.clone.wtTable.holder;
      var hider = this.clone.wtTable.hider;
      var holderStyle = holder.style;
      var hidderStyle = hider.style;
      var rootStyle = holder.parentNode.style;

      (0, _array.arrayEach)([holderStyle, hidderStyle, rootStyle], function (style) {
        style.width = '';
        style.height = '';
      });
    }

    /**
     * Destroy overlay instance
     */

  }, {
    key: 'destroy',
    value: function destroy() {
      new _eventManager2.default(this.clone).destroy();
    }
  }]);

  return Overlay;
}();

exports.default = Overlay;

/***/ }),
/* 30 */
/***/ (function(module, exports, __webpack_require__) {

// optional / simple context binding
var aFunction = __webpack_require__(54);
module.exports = function (fn, that, length) {
  aFunction(fn);
  if (that === undefined) return fn;
  switch (length) {
    case 1: return function (a) {
      return fn.call(that, a);
    };
    case 2: return function (a, b) {
      return fn.call(that, a, b);
    };
    case 3: return function (a, b, c) {
      return fn.call(that, a, b, c);
    };
  }
  return function (/* ...args */) {
    return fn.apply(that, arguments);
  };
};


/***/ }),
/* 31 */
/***/ (function(module, exports, __webpack_require__) {

var dP = __webpack_require__(18);
var createDesc = __webpack_require__(49);
module.exports = __webpack_require__(20) ? function (object, key, value) {
  return dP.f(object, key, createDesc(1, value));
} : function (object, key, value) {
  object[key] = value;
  return object;
};


/***/ }),
/* 32 */
/***/ (function(module, exports, __webpack_require__) {

var global = __webpack_require__(10);
var hide = __webpack_require__(31);
var has = __webpack_require__(26);
var SRC = __webpack_require__(51)('src');
var TO_STRING = 'toString';
var $toString = Function[TO_STRING];
var TPL = ('' + $toString).split(TO_STRING);

__webpack_require__(45).inspectSource = function (it) {
  return $toString.call(it);
};

(module.exports = function (O, key, val, safe) {
  var isFunction = typeof val == 'function';
  if (isFunction) has(val, 'name') || hide(val, 'name', key);
  if (O[key] === val) return;
  if (isFunction) has(val, SRC) || hide(val, SRC, O[key] ? '' + O[key] : TPL.join(String(key)));
  if (O === global) {
    O[key] = val;
  } else if (!safe) {
    delete O[key];
    hide(O, key, val);
  } else if (O[key]) {
    O[key] = val;
  } else {
    hide(O, key, val);
  }
// add fake Function#toString for correct work wrapped methods / constructors with methods like LoDash isNative
})(Function.prototype, TO_STRING, function toString() {
  return typeof this == 'function' && this[SRC] || $toString.call(this);
});


/***/ }),
/* 33 */
/***/ (function(module, exports) {

// 7.2.1 RequireObjectCoercible(argument)
module.exports = function (it) {
  if (it == undefined) throw TypeError("Can't call method on  " + it);
  return it;
};


/***/ }),
/* 34 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


exports.__esModule = true;

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

exports.requestAnimationFrame = requestAnimationFrame;
exports.cancelAnimationFrame = cancelAnimationFrame;
exports.isTouchSupported = isTouchSupported;
exports.isWebComponentSupportedNatively = isWebComponentSupportedNatively;
exports.hasCaptionProblem = hasCaptionProblem;
exports.getComparisonFunction = getComparisonFunction;
// https://gist.github.com/paulirish/1579671
var lastTime = 0;
var vendors = ['ms', 'moz', 'webkit', 'o'];
var _requestAnimationFrame = window.requestAnimationFrame;
var _cancelAnimationFrame = window.cancelAnimationFrame;

for (var x = 0; x < vendors.length && !_requestAnimationFrame; ++x) {
  _requestAnimationFrame = window[vendors[x] + 'RequestAnimationFrame'];
  _cancelAnimationFrame = window[vendors[x] + 'CancelAnimationFrame'] || window[vendors[x] + 'CancelRequestAnimationFrame'];
}

if (!_requestAnimationFrame) {
  _requestAnimationFrame = function _requestAnimationFrame(callback) {
    var currTime = new Date().getTime();
    var timeToCall = Math.max(0, 16 - (currTime - lastTime));
    var id = window.setTimeout(function () {
      callback(currTime + timeToCall);
    }, timeToCall);
    lastTime = currTime + timeToCall;

    return id;
  };
}

if (!_cancelAnimationFrame) {
  _cancelAnimationFrame = function _cancelAnimationFrame(id) {
    clearTimeout(id);
  };
}

/**
 * Polyfill for requestAnimationFrame
 *
 * @param {Function} callback
 * @returns {Number}
 */
function requestAnimationFrame(callback) {
  return _requestAnimationFrame.call(window, callback);
}

/**
 * Polyfill for cancelAnimationFrame
 *
 * @param {Number} id
 */
function cancelAnimationFrame(id) {
  _cancelAnimationFrame.call(window, id);
}

function isTouchSupported() {
  return 'ontouchstart' in window;
}

/**
 * Checks if browser is support web components natively
 *
 * @returns {Boolean}
 */
function isWebComponentSupportedNatively() {
  var test = document.createElement('div');

  return !!(test.createShadowRoot && test.createShadowRoot.toString().match(/\[native code\]/));
}

var _hasCaptionProblem;

function detectCaptionProblem() {
  var TABLE = document.createElement('TABLE');
  TABLE.style.borderSpacing = 0;
  TABLE.style.borderWidth = 0;
  TABLE.style.padding = 0;
  var TBODY = document.createElement('TBODY');
  TABLE.appendChild(TBODY);
  TBODY.appendChild(document.createElement('TR'));
  TBODY.firstChild.appendChild(document.createElement('TD'));
  TBODY.firstChild.firstChild.innerHTML = '<tr><td>t<br>t</td></tr>';

  var CAPTION = document.createElement('CAPTION');
  CAPTION.innerHTML = 'c<br>c<br>c<br>c';
  CAPTION.style.padding = 0;
  CAPTION.style.margin = 0;
  TABLE.insertBefore(CAPTION, TBODY);

  document.body.appendChild(TABLE);
  _hasCaptionProblem = TABLE.offsetHeight < 2 * TABLE.lastChild.offsetHeight; // boolean
  document.body.removeChild(TABLE);
}

function hasCaptionProblem() {
  if (_hasCaptionProblem === void 0) {
    detectCaptionProblem();
  }

  return _hasCaptionProblem;
}

var comparisonFunction = void 0;

/**
 * Get string comparison function for sorting purposes. It supports multilingual string comparison base on Internationalization API.
 *
 * @param {String} [language]
 * @param {Object} [options]
 * @returns {*}
 */
function getComparisonFunction(language) {
  var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};

  if (comparisonFunction) {
    return comparisonFunction;
  }

  if ((typeof Intl === 'undefined' ? 'undefined' : _typeof(Intl)) === 'object') {
    comparisonFunction = new Intl.Collator(language, options).compare;
  } else if (typeof String.prototype.localeCompare === 'function') {
    comparisonFunction = function comparisonFunction(a, b) {
      return ('' + a).localeCompare(b);
    };
  } else {
    comparisonFunction = function comparisonFunction(a, b) {
      if (a === b) {
        return 0;
      }

      return a > b ? -1 : 1;
    };
  }

  return comparisonFunction;
}

/***/ }),
/* 35 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


exports.__esModule = true;
exports.isFunction = isFunction;
exports.throttle = throttle;
exports.throttleAfterHits = throttleAfterHits;
exports.debounce = debounce;
exports.pipe = pipe;
exports.partial = partial;
exports.curry = curry;
exports.curryRight = curryRight;

var _array = __webpack_require__(2);

/**
 * Checks if given variable is function.
 *
 * @param {*} func Variable to check.
 * @returns {Boolean}
 */
function isFunction(func) {
  return typeof func === 'function';
}

/**
 * Creates throttle function that enforces a maximum number of times a function (`func`) can be called over time (`wait`).
 *
 * @param {Function} func Function to invoke.
 * @param {Number} wait Delay in miliseconds.
 * @returns {Function}
 */
function throttle(func) {
  var wait = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 200;

  var lastCalled = 0;
  var result = {
    lastCallThrottled: true
  };
  var lastTimer = null;

  function _throttle() {
    var _this = this;

    var args = arguments;
    var stamp = Date.now();
    var needCall = false;

    result.lastCallThrottled = true;

    if (!lastCalled) {
      lastCalled = stamp;
      needCall = true;
    }
    var remaining = wait - (stamp - lastCalled);

    if (needCall) {
      result.lastCallThrottled = false;
      func.apply(this, args);
    } else {
      if (lastTimer) {
        clearTimeout(lastTimer);
      }
      lastTimer = setTimeout(function () {
        result.lastCallThrottled = false;
        func.apply(_this, args);
        lastCalled = 0;
        lastTimer = void 0;
      }, remaining);
    }

    return result;
  }

  return _throttle;
}

/**
 * Creates throttle function that enforces a maximum number of times a function (`func`) can be called over
 * time (`wait`) after specified hits.
 *
 * @param {Function} func Function to invoke.
 * @param {Number} wait Delay in miliseconds.
 * @param {Number} hits Number of hits after throttling will be applied.
 * @returns {Function}
 */
function throttleAfterHits(func) {
  var wait = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 200;
  var hits = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 10;

  var funcThrottle = throttle(func, wait);
  var remainHits = hits;

  function _clearHits() {
    remainHits = hits;
  }
  function _throttleAfterHits() {
    if (remainHits) {
      remainHits--;

      return func.apply(this, arguments);
    }

    return funcThrottle.apply(this, arguments);
  }
  _throttleAfterHits.clearHits = _clearHits;

  return _throttleAfterHits;
}

/**
 * Creates debounce function that enforces a function (`func`) not be called again until a certain amount of time (`wait`)
 * has passed without it being called.
 *
 * @param {Function} func Function to invoke.
 * @param {Number} wait Delay in milliseconds.
 * @returns {Function}
 */
function debounce(func) {
  var wait = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 200;

  var lastTimer = null;
  var result = void 0;

  function _debounce() {
    var _this2 = this;

    var args = arguments;

    if (lastTimer) {
      clearTimeout(lastTimer);
    }
    lastTimer = setTimeout(function () {
      result = func.apply(_this2, args);
    }, wait);

    return result;
  }

  return _debounce;
}

/**
 * Creates the function that returns the result of calling the given functions. Result of the first function is passed to
 * the second as an argument and so on. Only first function in the chain can handle multiple arguments.
 *
 * @param {Function} functions Functions to compose.
 * @returns {Function}
 */
function pipe() {
  for (var _len = arguments.length, functions = Array(_len), _key = 0; _key < _len; _key++) {
    functions[_key] = arguments[_key];
  }

  var firstFunc = functions[0],
      restFunc = functions.slice(1);


  return function _pipe() {
    return (0, _array.arrayReduce)(restFunc, function (acc, fn) {
      return fn(acc);
    }, firstFunc.apply(this, arguments));
  };
}

/**
 * Creates the function that returns the function with cached arguments.
 *
 * @param {Function} func Function to partialization.
 * @param {Array} params Function arguments to cache.
 * @returns {Function}
 */
function partial(func) {
  for (var _len2 = arguments.length, params = Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) {
    params[_key2 - 1] = arguments[_key2];
  }

  return function _partial() {
    for (var _len3 = arguments.length, restParams = Array(_len3), _key3 = 0; _key3 < _len3; _key3++) {
      restParams[_key3] = arguments[_key3];
    }

    return func.apply(this, params.concat(restParams));
  };
}

/**
 * Creates the functions that returns the function with cached arguments. If count if passed arguments will be matched
 * to the arguments defined in `func` then function will be invoked.
 * Arguments are added to the stack in direction from the left to the right.
 *
 * @example
 * ```
 * var replace = curry(function(find, replace, string) {
 *   return string.replace(find, replace);
 * });
 *
 * // returns function with bounded first argument
 * var replace = replace('foo')
 *
 * // returns replaced string - all arguments was passed so function was invoked
 * replace('bar', 'Some test with foo...');
 *
 * ```
 *
 * @param {Function} func Function to currying.
 * @returns {Function}
 */
function curry(func) {
  var argsLength = func.length;

  function given(argsSoFar) {
    return function _curry() {
      for (var _len4 = arguments.length, params = Array(_len4), _key4 = 0; _key4 < _len4; _key4++) {
        params[_key4] = arguments[_key4];
      }

      var passedArgsSoFar = argsSoFar.concat(params);
      var result = void 0;

      if (passedArgsSoFar.length >= argsLength) {
        result = func.apply(this, passedArgsSoFar);
      } else {
        result = given(passedArgsSoFar);
      }

      return result;
    };
  }

  return given([]);
}

/**
 * Creates the functions that returns the function with cached arguments. If count if passed arguments will be matched
 * to the arguments defined in `func` then function will be invoked.
 * Arguments are added to the stack in direction from the right to the left.
 *
 * @example
 * ```
 * var replace = curry(function(find, replace, string) {
 *   return string.replace(find, replace);
 * });
 *
 * // returns function with bounded first argument
 * var replace = replace('Some test with foo...')
 *
 * // returns replaced string - all arguments was passed so function was invoked
 * replace('bar', 'foo');
 *
 * ```
 *
 * @param {Function} func Function to currying.
 * @returns {Function}
 */
function curryRight(func) {
  var argsLength = func.length;

  function given(argsSoFar) {
    return function _curry() {
      for (var _len5 = arguments.length, params = Array(_len5), _key5 = 0; _key5 < _len5; _key5++) {
        params[_key5] = arguments[_key5];
      }

      var passedArgsSoFar = argsSoFar.concat(params.reverse());
      var result = void 0;

      if (passedArgsSoFar.length >= argsLength) {
        result = func.apply(this, passedArgsSoFar);
      } else {
        result = given(passedArgsSoFar);
      }

      return result;
    };
  }

  return given([]);
}

/***/ }),
/* 36 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


exports.__esModule = true;
exports.EditorState = undefined;

var _src = __webpack_require__(14);

var _mixed = __webpack_require__(23);

var EditorState = exports.EditorState = {
  VIRGIN: 'STATE_VIRGIN', // before editing
  EDITING: 'STATE_EDITING',
  WAITING: 'STATE_WAITING', // waiting for async validation
  FINISHED: 'STATE_FINISHED'
};

function BaseEditor(instance) {
  this.instance = instance;
  this.state = EditorState.VIRGIN;

  this._opened = false;
  this._fullEditMode = false;
  this._closeCallback = null;

  this.init();
}

BaseEditor.prototype._fireCallbacks = function (result) {
  if (this._closeCallback) {
    this._closeCallback(result);
    this._closeCallback = null;
  }
};

BaseEditor.prototype.init = function () {};

BaseEditor.prototype.getValue = function () {
  throw Error('Editor getValue() method unimplemented');
};

BaseEditor.prototype.setValue = function (newValue) {
  throw Error('Editor setValue() method unimplemented');
};

BaseEditor.prototype.open = function () {
  throw Error('Editor open() method unimplemented');
};

BaseEditor.prototype.close = function () {
  throw Error('Editor close() method unimplemented');
};

BaseEditor.prototype.prepare = function (row, col, prop, td, originalValue, cellProperties) {
  this.TD = td;
  this.row = row;
  this.col = col;
  this.prop = prop;
  this.originalValue = originalValue;
  this.cellProperties = cellProperties;
  this.state = EditorState.VIRGIN;
};

BaseEditor.prototype.extend = function () {
  var baseClass = this.constructor;

  function Editor() {
    baseClass.apply(this, arguments);
  }

  function inherit(Child, Parent) {
    function Bridge() {}
    Bridge.prototype = Parent.prototype;
    Child.prototype = new Bridge();
    Child.prototype.constructor = Child;

    return Child;
  }

  return inherit(Editor, baseClass);
};

BaseEditor.prototype.saveValue = function (value, ctrlDown) {
  var selection = void 0;
  var tmp = void 0;

  // if ctrl+enter and multiple cells selected, behave like Excel (finish editing and apply to all cells)
  if (ctrlDown) {
    selection = this.instance.getSelected();

    if (selection[0] > selection[2]) {
      tmp = selection[0];
      selection[0] = selection[2];
      selection[2] = tmp;
    }
    if (selection[1] > selection[3]) {
      tmp = selection[1];
      selection[1] = selection[3];
      selection[3] = tmp;
    }
  } else {
    selection = [this.row, this.col, null, null];
  }

  this.instance.populateFromArray(selection[0], selection[1], value, selection[2], selection[3], 'edit');
};

BaseEditor.prototype.beginEditing = function (initialValue, event) {
  if (this.state != EditorState.VIRGIN) {
    return;
  }
  this.instance.view.scrollViewport(new _src.CellCoords(this.row, this.col));
  this.instance.view.render();
  this.state = EditorState.EDITING;

  initialValue = typeof initialValue == 'string' ? initialValue : this.originalValue;
  this.setValue((0, _mixed.stringify)(initialValue));

  this.open(event);
  this._opened = true;
  this.focus();

  // only rerender the selections (FillHandle should disappear when beginediting is triggered)
  this.instance.view.render();

  this.instance.runHooks('afterBeginEditing', this.row, this.col);
};

BaseEditor.prototype.finishEditing = function (restoreOriginalValue, ctrlDown, callback) {
  var _this = this,
      val;

  if (callback) {
    var previousCloseCallback = this._closeCallback;

    this._closeCallback = function (result) {
      if (previousCloseCallback) {
        previousCloseCallback(result);
      }

      callback(result);
      _this.instance.view.render();
    };
  }

  if (this.isWaiting()) {
    return;
  }

  if (this.state == EditorState.VIRGIN) {
    this.instance._registerTimeout(setTimeout(function () {
      _this._fireCallbacks(true);
    }, 0));

    return;
  }

  if (this.state == EditorState.EDITING) {
    if (restoreOriginalValue) {
      this.cancelChanges();
      this.instance.view.render();

      return;
    }

    var value = this.getValue();

    if (this.instance.getSettings().trimWhitespace) {
      // We trim only string values
      val = [[typeof value === 'string' ? String.prototype.trim.call(value || '') : value]];
    } else {
      val = [[value]];
    }

    this.state = EditorState.WAITING;
    this.saveValue(val, ctrlDown);

    if (this.instance.getCellValidator(this.cellProperties)) {
      this.instance.addHookOnce('postAfterValidate', function (result) {
        _this.state = EditorState.FINISHED;
        _this.discardEditor(result);
      });
    } else {
      this.state = EditorState.FINISHED;
      this.discardEditor(true);
    }
  }
};

BaseEditor.prototype.cancelChanges = function () {
  this.state = EditorState.FINISHED;
  this.discardEditor();
};

BaseEditor.prototype.discardEditor = function (result) {
  if (this.state !== EditorState.FINISHED) {
    return;
  }
  // validator was defined and failed
  if (result === false && this.cellProperties.allowInvalid !== true) {
    this.instance.selectCell(this.row, this.col);
    this.focus();
    this.state = EditorState.EDITING;
    this._fireCallbacks(false);
  } else {
    this.close();
    this._opened = false;
    this._fullEditMode = false;
    this.state = EditorState.VIRGIN;
    this._fireCallbacks(true);
  }
};

/**
 * Switch editor into full edit mode. In this state navigation keys don't close editor. This mode is activated
 * automatically after hit ENTER or F2 key on the cell or while editing cell press F2 key.
 */
BaseEditor.prototype.enableFullEditMode = function () {
  this._fullEditMode = true;
};

/**
 * Checks if editor is in full edit mode.
 *
 * @returns {Boolean}
 */
BaseEditor.prototype.isInFullEditMode = function () {
  return this._fullEditMode;
};

BaseEditor.prototype.isOpened = function () {
  return this._opened;
};

BaseEditor.prototype.isWaiting = function () {
  return this.state === EditorState.WAITING;
};

BaseEditor.prototype.checkEditorSection = function () {
  var totalRows = this.instance.countRows();
  var section = '';

  if (this.row < this.instance.getSettings().fixedRowsTop) {
    if (this.col < this.instance.getSettings().fixedColumnsLeft) {
      section = 'top-left-corner';
    } else {
      section = 'top';
    }
  } else if (this.instance.getSettings().fixedRowsBottom && this.row >= totalRows - this.instance.getSettings().fixedRowsBottom) {
    if (this.col < this.instance.getSettings().fixedColumnsLeft) {
      section = 'bottom-left-corner';
    } else {
      section = 'bottom';
    }
  } else if (this.col < this.instance.getSettings().fixedColumnsLeft) {
    section = 'left';
  }

  return section;
};

exports.default = BaseEditor;

/***/ }),
/* 37 */
/***/ (function(module, exports, __webpack_require__) {

// 22.1.3.31 Array.prototype[@@unscopables]
var UNSCOPABLES = __webpack_require__(8)('unscopables');
var ArrayProto = Array.prototype;
if (ArrayProto[UNSCOPABLES] == undefined) __webpack_require__(31)(ArrayProto, UNSCOPABLES, {});
module.exports = function (key) {
  ArrayProto[UNSCOPABLES][key] = true;
};


/***/ }),
/* 38 */
/***/ (function(module, exports) {

var toString = {}.toString;

module.exports = function (it) {
  return toString.call(it).slice(8, -1);
};


/***/ }),
/* 39 */
/***/ (function(module, exports, __webpack_require__) {

// 19.1.2.14 / 15.2.3.14 Object.keys(O)
var $keys = __webpack_require__(285);
var enumBugKeys = __webpack_require__(76);

module.exports = Object.keys || function keys(O) {
  return $keys(O, enumBugKeys);
};


/***/ }),
/* 40 */
/***/ (function(module, exports, __webpack_require__) {

// 7.1.13 ToObject(argument)
var defined = __webpack_require__(33);
module.exports = function (it) {
  return Object(defined(it));
};


/***/ }),
/* 41 */
/***/ (function(module, exports, __webpack_require__) {

var isObject = __webpack_require__(12);
module.exports = function (it, TYPE) {
  if (!isObject(it) || it._t !== TYPE) throw TypeError('Incompatible receiver, ' + TYPE + ' required!');
  return it;
};


/***/ }),
/* 42 */
/***/ (function(module, exports, __webpack_require__) {

/* WEBPACK VAR INJECTION */(function(module) {//! moment.js
//! version : 2.18.1
//! authors : Tim Wood, Iskren Chernev, Moment.js contributors
//! license : MIT
//! momentjs.com

;(function (global, factory) {
     true ? module.exports = factory() :
    typeof define === 'function' && define.amd ? define(factory) :
    global.moment = factory()
}(this, (function () { 'use strict';

var hookCallback;

function hooks () {
    return hookCallback.apply(null, arguments);
}

// This is done to register the method called with moment()
// without creating circular dependencies.
function setHookCallback (callback) {
    hookCallback = callback;
}

function isArray(input) {
    return input instanceof Array || Object.prototype.toString.call(input) === '[object Array]';
}

function isObject(input) {
    // IE8 will treat undefined and null as object if it wasn't for
    // input != null
    return input != null && Object.prototype.toString.call(input) === '[object Object]';
}

function isObjectEmpty(obj) {
    var k;
    for (k in obj) {
        // even if its not own property I'd still call it non-empty
        return false;
    }
    return true;
}

function isUndefined(input) {
    return input === void 0;
}

function isNumber(input) {
    return typeof input === 'number' || Object.prototype.toString.call(input) === '[object Number]';
}

function isDate(input) {
    return input instanceof Date || Object.prototype.toString.call(input) === '[object Date]';
}

function map(arr, fn) {
    var res = [], i;
    for (i = 0; i < arr.length; ++i) {
        res.push(fn(arr[i], i));
    }
    return res;
}

function hasOwnProp(a, b) {
    return Object.prototype.hasOwnProperty.call(a, b);
}

function extend(a, b) {
    for (var i in b) {
        if (hasOwnProp(b, i)) {
            a[i] = b[i];
        }
    }

    if (hasOwnProp(b, 'toString')) {
        a.toString = b.toString;
    }

    if (hasOwnProp(b, 'valueOf')) {
        a.valueOf = b.valueOf;
    }

    return a;
}

function createUTC (input, format, locale, strict) {
    return createLocalOrUTC(input, format, locale, strict, true).utc();
}

function defaultParsingFlags() {
    // We need to deep clone this object.
    return {
        empty           : false,
        unusedTokens    : [],
        unusedInput     : [],
        overflow        : -2,
        charsLeftOver   : 0,
        nullInput       : false,
        invalidMonth    : null,
        invalidFormat   : false,
        userInvalidated : false,
        iso             : false,
        parsedDateParts : [],
        meridiem        : null,
        rfc2822         : false,
        weekdayMismatch : false
    };
}

function getParsingFlags(m) {
    if (m._pf == null) {
        m._pf = defaultParsingFlags();
    }
    return m._pf;
}

var some;
if (Array.prototype.some) {
    some = Array.prototype.some;
} else {
    some = function (fun) {
        var t = Object(this);
        var len = t.length >>> 0;

        for (var i = 0; i < len; i++) {
            if (i in t && fun.call(this, t[i], i, t)) {
                return true;
            }
        }

        return false;
    };
}

var some$1 = some;

function isValid(m) {
    if (m._isValid == null) {
        var flags = getParsingFlags(m);
        var parsedParts = some$1.call(flags.parsedDateParts, function (i) {
            return i != null;
        });
        var isNowValid = !isNaN(m._d.getTime()) &&
            flags.overflow < 0 &&
            !flags.empty &&
            !flags.invalidMonth &&
            !flags.invalidWeekday &&
            !flags.nullInput &&
            !flags.invalidFormat &&
            !flags.userInvalidated &&
            (!flags.meridiem || (flags.meridiem && parsedParts));

        if (m._strict) {
            isNowValid = isNowValid &&
                flags.charsLeftOver === 0 &&
                flags.unusedTokens.length === 0 &&
                flags.bigHour === undefined;
        }

        if (Object.isFrozen == null || !Object.isFrozen(m)) {
            m._isValid = isNowValid;
        }
        else {
            return isNowValid;
        }
    }
    return m._isValid;
}

function createInvalid (flags) {
    var m = createUTC(NaN);
    if (flags != null) {
        extend(getParsingFlags(m), flags);
    }
    else {
        getParsingFlags(m).userInvalidated = true;
    }

    return m;
}

// Plugins that add properties should also add the key here (null value),
// so we can properly clone ourselves.
var momentProperties = hooks.momentProperties = [];

function copyConfig(to, from) {
    var i, prop, val;

    if (!isUndefined(from._isAMomentObject)) {
        to._isAMomentObject = from._isAMomentObject;
    }
    if (!isUndefined(from._i)) {
        to._i = from._i;
    }
    if (!isUndefined(from._f)) {
        to._f = from._f;
    }
    if (!isUndefined(from._l)) {
        to._l = from._l;
    }
    if (!isUndefined(from._strict)) {
        to._strict = from._strict;
    }
    if (!isUndefined(from._tzm)) {
        to._tzm = from._tzm;
    }
    if (!isUndefined(from._isUTC)) {
        to._isUTC = from._isUTC;
    }
    if (!isUndefined(from._offset)) {
        to._offset = from._offset;
    }
    if (!isUndefined(from._pf)) {
        to._pf = getParsingFlags(from);
    }
    if (!isUndefined(from._locale)) {
        to._locale = from._locale;
    }

    if (momentProperties.length > 0) {
        for (i = 0; i < momentProperties.length; i++) {
            prop = momentProperties[i];
            val = from[prop];
            if (!isUndefined(val)) {
                to[prop] = val;
            }
        }
    }

    return to;
}

var updateInProgress = false;

// Moment prototype object
function Moment(config) {
    copyConfig(this, config);
    this._d = new Date(config._d != null ? config._d.getTime() : NaN);
    if (!this.isValid()) {
        this._d = new Date(NaN);
    }
    // Prevent infinite loop in case updateOffset creates new moment
    // objects.
    if (updateInProgress === false) {
        updateInProgress = true;
        hooks.updateOffset(this);
        updateInProgress = false;
    }
}

function isMoment (obj) {
    return obj instanceof Moment || (obj != null && obj._isAMomentObject != null);
}

function absFloor (number) {
    if (number < 0) {
        // -0 -> 0
        return Math.ceil(number) || 0;
    } else {
        return Math.floor(number);
    }
}

function toInt(argumentForCoercion) {
    var coercedNumber = +argumentForCoercion,
        value = 0;

    if (coercedNumber !== 0 && isFinite(coercedNumber)) {
        value = absFloor(coercedNumber);
    }

    return value;
}

// compare two arrays, return the number of differences
function compareArrays(array1, array2, dontConvert) {
    var len = Math.min(array1.length, array2.length),
        lengthDiff = Math.abs(array1.length - array2.length),
        diffs = 0,
        i;
    for (i = 0; i < len; i++) {
        if ((dontConvert && array1[i] !== array2[i]) ||
            (!dontConvert && toInt(array1[i]) !== toInt(array2[i]))) {
            diffs++;
        }
    }
    return diffs + lengthDiff;
}

function warn(msg) {
    if (hooks.suppressDeprecationWarnings === false &&
            (typeof console !==  'undefined') && console.warn) {
        console.warn('Deprecation warning: ' + msg);
    }
}

function deprecate(msg, fn) {
    var firstTime = true;

    return extend(function () {
        if (hooks.deprecationHandler != null) {
            hooks.deprecationHandler(null, msg);
        }
        if (firstTime) {
            var args = [];
            var arg;
            for (var i = 0; i < arguments.length; i++) {
                arg = '';
                if (typeof arguments[i] === 'object') {
                    arg += '\n[' + i + '] ';
                    for (var key in arguments[0]) {
                        arg += key + ': ' + arguments[0][key] + ', ';
                    }
                    arg = arg.slice(0, -2); // Remove trailing comma and space
                } else {
                    arg = arguments[i];
                }
                args.push(arg);
            }
            warn(msg + '\nArguments: ' + Array.prototype.slice.call(args).join('') + '\n' + (new Error()).stack);
            firstTime = false;
        }
        return fn.apply(this, arguments);
    }, fn);
}

var deprecations = {};

function deprecateSimple(name, msg) {
    if (hooks.deprecationHandler != null) {
        hooks.deprecationHandler(name, msg);
    }
    if (!deprecations[name]) {
        warn(msg);
        deprecations[name] = true;
    }
}

hooks.suppressDeprecationWarnings = false;
hooks.deprecationHandler = null;

function isFunction(input) {
    return input instanceof Function || Object.prototype.toString.call(input) === '[object Function]';
}

function set (config) {
    var prop, i;
    for (i in config) {
        prop = config[i];
        if (isFunction(prop)) {
            this[i] = prop;
        } else {
            this['_' + i] = prop;
        }
    }
    this._config = config;
    // Lenient ordinal parsing accepts just a number in addition to
    // number + (possibly) stuff coming from _dayOfMonthOrdinalParse.
    // TODO: Remove "ordinalParse" fallback in next major release.
    this._dayOfMonthOrdinalParseLenient = new RegExp(
        (this._dayOfMonthOrdinalParse.source || this._ordinalParse.source) +
            '|' + (/\d{1,2}/).source);
}

function mergeConfigs(parentConfig, childConfig) {
    var res = extend({}, parentConfig), prop;
    for (prop in childConfig) {
        if (hasOwnProp(childConfig, prop)) {
            if (isObject(parentConfig[prop]) && isObject(childConfig[prop])) {
                res[prop] = {};
                extend(res[prop], parentConfig[prop]);
                extend(res[prop], childConfig[prop]);
            } else if (childConfig[prop] != null) {
                res[prop] = childConfig[prop];
            } else {
                delete res[prop];
            }
        }
    }
    for (prop in parentConfig) {
        if (hasOwnProp(parentConfig, prop) &&
                !hasOwnProp(childConfig, prop) &&
                isObject(parentConfig[prop])) {
            // make sure changes to properties don't modify parent config
            res[prop] = extend({}, res[prop]);
        }
    }
    return res;
}

function Locale(config) {
    if (config != null) {
        this.set(config);
    }
}

var keys;

if (Object.keys) {
    keys = Object.keys;
} else {
    keys = function (obj) {
        var i, res = [];
        for (i in obj) {
            if (hasOwnProp(obj, i)) {
                res.push(i);
            }
        }
        return res;
    };
}

var keys$1 = keys;

var defaultCalendar = {
    sameDay : '[Today at] LT',
    nextDay : '[Tomorrow at] LT',
    nextWeek : 'dddd [at] LT',
    lastDay : '[Yesterday at] LT',
    lastWeek : '[Last] dddd [at] LT',
    sameElse : 'L'
};

function calendar (key, mom, now) {
    var output = this._calendar[key] || this._calendar['sameElse'];
    return isFunction(output) ? output.call(mom, now) : output;
}

var defaultLongDateFormat = {
    LTS  : 'h:mm:ss A',
    LT   : 'h:mm A',
    L    : 'MM/DD/YYYY',
    LL   : 'MMMM D, YYYY',
    LLL  : 'MMMM D, YYYY h:mm A',
    LLLL : 'dddd, MMMM D, YYYY h:mm A'
};

function longDateFormat (key) {
    var format = this._longDateFormat[key],
        formatUpper = this._longDateFormat[key.toUpperCase()];

    if (format || !formatUpper) {
        return format;
    }

    this._longDateFormat[key] = formatUpper.replace(/MMMM|MM|DD|dddd/g, function (val) {
        return val.slice(1);
    });

    return this._longDateFormat[key];
}

var defaultInvalidDate = 'Invalid date';

function invalidDate () {
    return this._invalidDate;
}

var defaultOrdinal = '%d';
var defaultDayOfMonthOrdinalParse = /\d{1,2}/;

function ordinal (number) {
    return this._ordinal.replace('%d', number);
}

var defaultRelativeTime = {
    future : 'in %s',
    past   : '%s ago',
    s  : 'a few seconds',
    ss : '%d seconds',
    m  : 'a minute',
    mm : '%d minutes',
    h  : 'an hour',
    hh : '%d hours',
    d  : 'a day',
    dd : '%d days',
    M  : 'a month',
    MM : '%d months',
    y  : 'a year',
    yy : '%d years'
};

function relativeTime (number, withoutSuffix, string, isFuture) {
    var output = this._relativeTime[string];
    return (isFunction(output)) ?
        output(number, withoutSuffix, string, isFuture) :
        output.replace(/%d/i, number);
}

function pastFuture (diff, output) {
    var format = this._relativeTime[diff > 0 ? 'future' : 'past'];
    return isFunction(format) ? format(output) : format.replace(/%s/i, output);
}

var aliases = {};

function addUnitAlias (unit, shorthand) {
    var lowerCase = unit.toLowerCase();
    aliases[lowerCase] = aliases[lowerCase + 's'] = aliases[shorthand] = unit;
}

function normalizeUnits(units) {
    return typeof units === 'string' ? aliases[units] || aliases[units.toLowerCase()] : undefined;
}

function normalizeObjectUnits(inputObject) {
    var normalizedInput = {},
        normalizedProp,
        prop;

    for (prop in inputObject) {
        if (hasOwnProp(inputObject, prop)) {
            normalizedProp = normalizeUnits(prop);
            if (normalizedProp) {
                normalizedInput[normalizedProp] = inputObject[prop];
            }
        }
    }

    return normalizedInput;
}

var priorities = {};

function addUnitPriority(unit, priority) {
    priorities[unit] = priority;
}

function getPrioritizedUnits(unitsObj) {
    var units = [];
    for (var u in unitsObj) {
        units.push({unit: u, priority: priorities[u]});
    }
    units.sort(function (a, b) {
        return a.priority - b.priority;
    });
    return units;
}

function makeGetSet (unit, keepTime) {
    return function (value) {
        if (value != null) {
            set$1(this, unit, value);
            hooks.updateOffset(this, keepTime);
            return this;
        } else {
            return get(this, unit);
        }
    };
}

function get (mom, unit) {
    return mom.isValid() ?
        mom._d['get' + (mom._isUTC ? 'UTC' : '') + unit]() : NaN;
}

function set$1 (mom, unit, value) {
    if (mom.isValid()) {
        mom._d['set' + (mom._isUTC ? 'UTC' : '') + unit](value);
    }
}

// MOMENTS

function stringGet (units) {
    units = normalizeUnits(units);
    if (isFunction(this[units])) {
        return this[units]();
    }
    return this;
}


function stringSet (units, value) {
    if (typeof units === 'object') {
        units = normalizeObjectUnits(units);
        var prioritized = getPrioritizedUnits(units);
        for (var i = 0; i < prioritized.length; i++) {
            this[prioritized[i].unit](units[prioritized[i].unit]);
        }
    } else {
        units = normalizeUnits(units);
        if (isFunction(this[units])) {
            return this[units](value);
        }
    }
    return this;
}

function zeroFill(number, targetLength, forceSign) {
    var absNumber = '' + Math.abs(number),
        zerosToFill = targetLength - absNumber.length,
        sign = number >= 0;
    return (sign ? (forceSign ? '+' : '') : '-') +
        Math.pow(10, Math.max(0, zerosToFill)).toString().substr(1) + absNumber;
}

var formattingTokens = /(\[[^\[]*\])|(\\)?([Hh]mm(ss)?|Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|Qo?|YYYYYY|YYYYY|YYYY|YY|gg(ggg?)?|GG(GGG?)?|e|E|a|A|hh?|HH?|kk?|mm?|ss?|S{1,9}|x|X|zz?|ZZ?|.)/g;

var localFormattingTokens = /(\[[^\[]*\])|(\\)?(LTS|LT|LL?L?L?|l{1,4})/g;

var formatFunctions = {};

var formatTokenFunctions = {};

// token:    'M'
// padded:   ['MM', 2]
// ordinal:  'Mo'
// callback: function () { this.month() + 1 }
function addFormatToken (token, padded, ordinal, callback) {
    var func = callback;
    if (typeof callback === 'string') {
        func = function () {
            return this[callback]();
        };
    }
    if (token) {
        formatTokenFunctions[token] = func;
    }
    if (padded) {
        formatTokenFunctions[padded[0]] = function () {
            return zeroFill(func.apply(this, arguments), padded[1], padded[2]);
        };
    }
    if (ordinal) {
        formatTokenFunctions[ordinal] = function () {
            return this.localeData().ordinal(func.apply(this, arguments), token);
        };
    }
}

function removeFormattingTokens(input) {
    if (input.match(/\[[\s\S]/)) {
        return input.replace(/^\[|\]$/g, '');
    }
    return input.replace(/\\/g, '');
}

function makeFormatFunction(format) {
    var array = format.match(formattingTokens), i, length;

    for (i = 0, length = array.length; i < length; i++) {
        if (formatTokenFunctions[array[i]]) {
            array[i] = formatTokenFunctions[array[i]];
        } else {
            array[i] = removeFormattingTokens(array[i]);
        }
    }

    return function (mom) {
        var output = '', i;
        for (i = 0; i < length; i++) {
            output += isFunction(array[i]) ? array[i].call(mom, format) : array[i];
        }
        return output;
    };
}

// format date using native date object
function formatMoment(m, format) {
    if (!m.isValid()) {
        return m.localeData().invalidDate();
    }

    format = expandFormat(format, m.localeData());
    formatFunctions[format] = formatFunctions[format] || makeFormatFunction(format);

    return formatFunctions[format](m);
}

function expandFormat(format, locale) {
    var i = 5;

    function replaceLongDateFormatTokens(input) {
        return locale.longDateFormat(input) || input;
    }

    localFormattingTokens.lastIndex = 0;
    while (i >= 0 && localFormattingTokens.test(format)) {
        format = format.replace(localFormattingTokens, replaceLongDateFormatTokens);
        localFormattingTokens.lastIndex = 0;
        i -= 1;
    }

    return format;
}

var match1         = /\d/;            //       0 - 9
var match2         = /\d\d/;          //      00 - 99
var match3         = /\d{3}/;         //     000 - 999
var match4         = /\d{4}/;         //    0000 - 9999
var match6         = /[+-]?\d{6}/;    // -999999 - 999999
var match1to2      = /\d\d?/;         //       0 - 99
var match3to4      = /\d\d\d\d?/;     //     999 - 9999
var match5to6      = /\d\d\d\d\d\d?/; //   99999 - 999999
var match1to3      = /\d{1,3}/;       //       0 - 999
var match1to4      = /\d{1,4}/;       //       0 - 9999
var match1to6      = /[+-]?\d{1,6}/;  // -999999 - 999999

var matchUnsigned  = /\d+/;           //       0 - inf
var matchSigned    = /[+-]?\d+/;      //    -inf - inf

var matchOffset    = /Z|[+-]\d\d:?\d\d/gi; // +00:00 -00:00 +0000 -0000 or Z
var matchShortOffset = /Z|[+-]\d\d(?::?\d\d)?/gi; // +00 -00 +00:00 -00:00 +0000 -0000 or Z

var matchTimestamp = /[+-]?\d+(\.\d{1,3})?/; // 123456789 123456789.123

// any word (or two) characters or numbers including two/three word month in arabic.
// includes scottish gaelic two word and hyphenated months
var matchWord = /[0-9]*['a-z\u00A0-\u05FF\u0700-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+|[\u0600-\u06FF\/]+(\s*?[\u0600-\u06FF]+){1,2}/i;


var regexes = {};

function addRegexToken (token, regex, strictRegex) {
    regexes[token] = isFunction(regex) ? regex : function (isStrict, localeData) {
        return (isStrict && strictRegex) ? strictRegex : regex;
    };
}

function getParseRegexForToken (token, config) {
    if (!hasOwnProp(regexes, token)) {
        return new RegExp(unescapeFormat(token));
    }

    return regexes[token](config._strict, config._locale);
}

// Code from http://stackoverflow.com/questions/3561493/is-there-a-regexp-escape-function-in-javascript
function unescapeFormat(s) {
    return regexEscape(s.replace('\\', '').replace(/\\(\[)|\\(\])|\[([^\]\[]*)\]|\\(.)/g, function (matched, p1, p2, p3, p4) {
        return p1 || p2 || p3 || p4;
    }));
}

function regexEscape(s) {
    return s.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');
}

var tokens = {};

function addParseToken (token, callback) {
    var i, func = callback;
    if (typeof token === 'string') {
        token = [token];
    }
    if (isNumber(callback)) {
        func = function (input, array) {
            array[callback] = toInt(input);
        };
    }
    for (i = 0; i < token.length; i++) {
        tokens[token[i]] = func;
    }
}

function addWeekParseToken (token, callback) {
    addParseToken(token, function (input, array, config, token) {
        config._w = config._w || {};
        callback(input, config._w, config, token);
    });
}

function addTimeToArrayFromToken(token, input, config) {
    if (input != null && hasOwnProp(tokens, token)) {
        tokens[token](input, config._a, config, token);
    }
}

var YEAR = 0;
var MONTH = 1;
var DATE = 2;
var HOUR = 3;
var MINUTE = 4;
var SECOND = 5;
var MILLISECOND = 6;
var WEEK = 7;
var WEEKDAY = 8;

var indexOf;

if (Array.prototype.indexOf) {
    indexOf = Array.prototype.indexOf;
} else {
    indexOf = function (o) {
        // I know
        var i;
        for (i = 0; i < this.length; ++i) {
            if (this[i] === o) {
                return i;
            }
        }
        return -1;
    };
}

var indexOf$1 = indexOf;

function daysInMonth(year, month) {
    return new Date(Date.UTC(year, month + 1, 0)).getUTCDate();
}

// FORMATTING

addFormatToken('M', ['MM', 2], 'Mo', function () {
    return this.month() + 1;
});

addFormatToken('MMM', 0, 0, function (format) {
    return this.localeData().monthsShort(this, format);
});

addFormatToken('MMMM', 0, 0, function (format) {
    return this.localeData().months(this, format);
});

// ALIASES

addUnitAlias('month', 'M');

// PRIORITY

addUnitPriority('month', 8);

// PARSING

addRegexToken('M',    match1to2);
addRegexToken('MM',   match1to2, match2);
addRegexToken('MMM',  function (isStrict, locale) {
    return locale.monthsShortRegex(isStrict);
});
addRegexToken('MMMM', function (isStrict, locale) {
    return locale.monthsRegex(isStrict);
});

addParseToken(['M', 'MM'], function (input, array) {
    array[MONTH] = toInt(input) - 1;
});

addParseToken(['MMM', 'MMMM'], function (input, array, config, token) {
    var month = config._locale.monthsParse(input, token, config._strict);
    // if we didn't find a month name, mark the date as invalid.
    if (month != null) {
        array[MONTH] = month;
    } else {
        getParsingFlags(config).invalidMonth = input;
    }
});

// LOCALES

var MONTHS_IN_FORMAT = /D[oD]?(\[[^\[\]]*\]|\s)+MMMM?/;
var defaultLocaleMonths = 'January_February_March_April_May_June_July_August_September_October_November_December'.split('_');
function localeMonths (m, format) {
    if (!m) {
        return isArray(this._months) ? this._months :
            this._months['standalone'];
    }
    return isArray(this._months) ? this._months[m.month()] :
        this._months[(this._months.isFormat || MONTHS_IN_FORMAT).test(format) ? 'format' : 'standalone'][m.month()];
}

var defaultLocaleMonthsShort = 'Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec'.split('_');
function localeMonthsShort (m, format) {
    if (!m) {
        return isArray(this._monthsShort) ? this._monthsShort :
            this._monthsShort['standalone'];
    }
    return isArray(this._monthsShort) ? this._monthsShort[m.month()] :
        this._monthsShort[MONTHS_IN_FORMAT.test(format) ? 'format' : 'standalone'][m.month()];
}

function handleStrictParse(monthName, format, strict) {
    var i, ii, mom, llc = monthName.toLocaleLowerCase();
    if (!this._monthsParse) {
        // this is not used
        this._monthsParse = [];
        this._longMonthsParse = [];
        this._shortMonthsParse = [];
        for (i = 0; i < 12; ++i) {
            mom = createUTC([2000, i]);
            this._shortMonthsParse[i] = this.monthsShort(mom, '').toLocaleLowerCase();
            this._longMonthsParse[i] = this.months(mom, '').toLocaleLowerCase();
        }
    }

    if (strict) {
        if (format === 'MMM') {
            ii = indexOf$1.call(this._shortMonthsParse, llc);
            return ii !== -1 ? ii : null;
        } else {
            ii = indexOf$1.call(this._longMonthsParse, llc);
            return ii !== -1 ? ii : null;
        }
    } else {
        if (format === 'MMM') {
            ii = indexOf$1.call(this._shortMonthsParse, llc);
            if (ii !== -1) {
                return ii;
            }
            ii = indexOf$1.call(this._longMonthsParse, llc);
            return ii !== -1 ? ii : null;
        } else {
            ii = indexOf$1.call(this._longMonthsParse, llc);
            if (ii !== -1) {
                return ii;
            }
            ii = indexOf$1.call(this._shortMonthsParse, llc);
            return ii !== -1 ? ii : null;
        }
    }
}

function localeMonthsParse (monthName, format, strict) {
    var i, mom, regex;

    if (this._monthsParseExact) {
        return handleStrictParse.call(this, monthName, format, strict);
    }

    if (!this._monthsParse) {
        this._monthsParse = [];
        this._longMonthsParse = [];
        this._shortMonthsParse = [];
    }

    // TODO: add sorting
    // Sorting makes sure if one month (or abbr) is a prefix of another
    // see sorting in computeMonthsParse
    for (i = 0; i < 12; i++) {
        // make the regex if we don't have it already
        mom = createUTC([2000, i]);
        if (strict && !this._longMonthsParse[i]) {
            this._longMonthsParse[i] = new RegExp('^' + this.months(mom, '').replace('.', '') + '$', 'i');
            this._shortMonthsParse[i] = new RegExp('^' + this.monthsShort(mom, '').replace('.', '') + '$', 'i');
        }
        if (!strict && !this._monthsParse[i]) {
            regex = '^' + this.months(mom, '') + '|^' + this.monthsShort(mom, '');
            this._monthsParse[i] = new RegExp(regex.replace('.', ''), 'i');
        }
        // test the regex
        if (strict && format === 'MMMM' && this._longMonthsParse[i].test(monthName)) {
            return i;
        } else if (strict && format === 'MMM' && this._shortMonthsParse[i].test(monthName)) {
            return i;
        } else if (!strict && this._monthsParse[i].test(monthName)) {
            return i;
        }
    }
}

// MOMENTS

function setMonth (mom, value) {
    var dayOfMonth;

    if (!mom.isValid()) {
        // No op
        return mom;
    }

    if (typeof value === 'string') {
        if (/^\d+$/.test(value)) {
            value = toInt(value);
        } else {
            value = mom.localeData().monthsParse(value);
            // TODO: Another silent failure?
            if (!isNumber(value)) {
                return mom;
            }
        }
    }

    dayOfMonth = Math.min(mom.date(), daysInMonth(mom.year(), value));
    mom._d['set' + (mom._isUTC ? 'UTC' : '') + 'Month'](value, dayOfMonth);
    return mom;
}

function getSetMonth (value) {
    if (value != null) {
        setMonth(this, value);
        hooks.updateOffset(this, true);
        return this;
    } else {
        return get(this, 'Month');
    }
}

function getDaysInMonth () {
    return daysInMonth(this.year(), this.month());
}

var defaultMonthsShortRegex = matchWord;
function monthsShortRegex (isStrict) {
    if (this._monthsParseExact) {
        if (!hasOwnProp(this, '_monthsRegex')) {
            computeMonthsParse.call(this);
        }
        if (isStrict) {
            return this._monthsShortStrictRegex;
        } else {
            return this._monthsShortRegex;
        }
    } else {
        if (!hasOwnProp(this, '_monthsShortRegex')) {
            this._monthsShortRegex = defaultMonthsShortRegex;
        }
        return this._monthsShortStrictRegex && isStrict ?
            this._monthsShortStrictRegex : this._monthsShortRegex;
    }
}

var defaultMonthsRegex = matchWord;
function monthsRegex (isStrict) {
    if (this._monthsParseExact) {
        if (!hasOwnProp(this, '_monthsRegex')) {
            computeMonthsParse.call(this);
        }
        if (isStrict) {
            return this._monthsStrictRegex;
        } else {
            return this._monthsRegex;
        }
    } else {
        if (!hasOwnProp(this, '_monthsRegex')) {
            this._monthsRegex = defaultMonthsRegex;
        }
        return this._monthsStrictRegex && isStrict ?
            this._monthsStrictRegex : this._monthsRegex;
    }
}

function computeMonthsParse () {
    function cmpLenRev(a, b) {
        return b.length - a.length;
    }

    var shortPieces = [], longPieces = [], mixedPieces = [],
        i, mom;
    for (i = 0; i < 12; i++) {
        // make the regex if we don't have it already
        mom = createUTC([2000, i]);
        shortPieces.push(this.monthsShort(mom, ''));
        longPieces.push(this.months(mom, ''));
        mixedPieces.push(this.months(mom, ''));
        mixedPieces.push(this.monthsShort(mom, ''));
    }
    // Sorting makes sure if one month (or abbr) is a prefix of another it
    // will match the longer piece.
    shortPieces.sort(cmpLenRev);
    longPieces.sort(cmpLenRev);
    mixedPieces.sort(cmpLenRev);
    for (i = 0; i < 12; i++) {
        shortPieces[i] = regexEscape(shortPieces[i]);
        longPieces[i] = regexEscape(longPieces[i]);
    }
    for (i = 0; i < 24; i++) {
        mixedPieces[i] = regexEscape(mixedPieces[i]);
    }

    this._monthsRegex = new RegExp('^(' + mixedPieces.join('|') + ')', 'i');
    this._monthsShortRegex = this._monthsRegex;
    this._monthsStrictRegex = new RegExp('^(' + longPieces.join('|') + ')', 'i');
    this._monthsShortStrictRegex = new RegExp('^(' + shortPieces.join('|') + ')', 'i');
}

// FORMATTING

addFormatToken('Y', 0, 0, function () {
    var y = this.year();
    return y <= 9999 ? '' + y : '+' + y;
});

addFormatToken(0, ['YY', 2], 0, function () {
    return this.year() % 100;
});

addFormatToken(0, ['YYYY',   4],       0, 'year');
addFormatToken(0, ['YYYYY',  5],       0, 'year');
addFormatToken(0, ['YYYYYY', 6, true], 0, 'year');

// ALIASES

addUnitAlias('year', 'y');

// PRIORITIES

addUnitPriority('year', 1);

// PARSING

addRegexToken('Y',      matchSigned);
addRegexToken('YY',     match1to2, match2);
addRegexToken('YYYY',   match1to4, match4);
addRegexToken('YYYYY',  match1to6, match6);
addRegexToken('YYYYYY', match1to6, match6);

addParseToken(['YYYYY', 'YYYYYY'], YEAR);
addParseToken('YYYY', function (input, array) {
    array[YEAR] = input.length === 2 ? hooks.parseTwoDigitYear(input) : toInt(input);
});
addParseToken('YY', function (input, array) {
    array[YEAR] = hooks.parseTwoDigitYear(input);
});
addParseToken('Y', function (input, array) {
    array[YEAR] = parseInt(input, 10);
});

// HELPERS

function daysInYear(year) {
    return isLeapYear(year) ? 366 : 365;
}

function isLeapYear(year) {
    return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0;
}

// HOOKS

hooks.parseTwoDigitYear = function (input) {
    return toInt(input) + (toInt(input) > 68 ? 1900 : 2000);
};

// MOMENTS

var getSetYear = makeGetSet('FullYear', true);

function getIsLeapYear () {
    return isLeapYear(this.year());
}

function createDate (y, m, d, h, M, s, ms) {
    // can't just apply() to create a date:
    // https://stackoverflow.com/q/181348
    var date = new Date(y, m, d, h, M, s, ms);

    // the date constructor remaps years 0-99 to 1900-1999
    if (y < 100 && y >= 0 && isFinite(date.getFullYear())) {
        date.setFullYear(y);
    }
    return date;
}

function createUTCDate (y) {
    var date = new Date(Date.UTC.apply(null, arguments));

    // the Date.UTC function remaps years 0-99 to 1900-1999
    if (y < 100 && y >= 0 && isFinite(date.getUTCFullYear())) {
        date.setUTCFullYear(y);
    }
    return date;
}

// start-of-first-week - start-of-year
function firstWeekOffset(year, dow, doy) {
    var // first-week day -- which january is always in the first week (4 for iso, 1 for other)
        fwd = 7 + dow - doy,
        // first-week day local weekday -- which local weekday is fwd
        fwdlw = (7 + createUTCDate(year, 0, fwd).getUTCDay() - dow) % 7;

    return -fwdlw + fwd - 1;
}

// https://en.wikipedia.org/wiki/ISO_week_date#Calculating_a_date_given_the_year.2C_week_number_and_weekday
function dayOfYearFromWeeks(year, week, weekday, dow, doy) {
    var localWeekday = (7 + weekday - dow) % 7,
        weekOffset = firstWeekOffset(year, dow, doy),
        dayOfYear = 1 + 7 * (week - 1) + localWeekday + weekOffset,
        resYear, resDayOfYear;

    if (dayOfYear <= 0) {
        resYear = year - 1;
        resDayOfYear = daysInYear(resYear) + dayOfYear;
    } else if (dayOfYear > daysInYear(year)) {
        resYear = year + 1;
        resDayOfYear = dayOfYear - daysInYear(year);
    } else {
        resYear = year;
        resDayOfYear = dayOfYear;
    }

    return {
        year: resYear,
        dayOfYear: resDayOfYear
    };
}

function weekOfYear(mom, dow, doy) {
    var weekOffset = firstWeekOffset(mom.year(), dow, doy),
        week = Math.floor((mom.dayOfYear() - weekOffset - 1) / 7) + 1,
        resWeek, resYear;

    if (week < 1) {
        resYear = mom.year() - 1;
        resWeek = week + weeksInYear(resYear, dow, doy);
    } else if (week > weeksInYear(mom.year(), dow, doy)) {
        resWeek = week - weeksInYear(mom.year(), dow, doy);
        resYear = mom.year() + 1;
    } else {
        resYear = mom.year();
        resWeek = week;
    }

    return {
        week: resWeek,
        year: resYear
    };
}

function weeksInYear(year, dow, doy) {
    var weekOffset = firstWeekOffset(year, dow, doy),
        weekOffsetNext = firstWeekOffset(year + 1, dow, doy);
    return (daysInYear(year) - weekOffset + weekOffsetNext) / 7;
}

// FORMATTING

addFormatToken('w', ['ww', 2], 'wo', 'week');
addFormatToken('W', ['WW', 2], 'Wo', 'isoWeek');

// ALIASES

addUnitAlias('week', 'w');
addUnitAlias('isoWeek', 'W');

// PRIORITIES

addUnitPriority('week', 5);
addUnitPriority('isoWeek', 5);

// PARSING

addRegexToken('w',  match1to2);
addRegexToken('ww', match1to2, match2);
addRegexToken('W',  match1to2);
addRegexToken('WW', match1to2, match2);

addWeekParseToken(['w', 'ww', 'W', 'WW'], function (input, week, config, token) {
    week[token.substr(0, 1)] = toInt(input);
});

// HELPERS

// LOCALES

function localeWeek (mom) {
    return weekOfYear(mom, this._week.dow, this._week.doy).week;
}

var defaultLocaleWeek = {
    dow : 0, // Sunday is the first day of the week.
    doy : 6  // The week that contains Jan 1st is the first week of the year.
};

function localeFirstDayOfWeek () {
    return this._week.dow;
}

function localeFirstDayOfYear () {
    return this._week.doy;
}

// MOMENTS

function getSetWeek (input) {
    var week = this.localeData().week(this);
    return input == null ? week : this.add((input - week) * 7, 'd');
}

function getSetISOWeek (input) {
    var week = weekOfYear(this, 1, 4).week;
    return input == null ? week : this.add((input - week) * 7, 'd');
}

// FORMATTING

addFormatToken('d', 0, 'do', 'day');

addFormatToken('dd', 0, 0, function (format) {
    return this.localeData().weekdaysMin(this, format);
});

addFormatToken('ddd', 0, 0, function (format) {
    return this.localeData().weekdaysShort(this, format);
});

addFormatToken('dddd', 0, 0, function (format) {
    return this.localeData().weekdays(this, format);
});

addFormatToken('e', 0, 0, 'weekday');
addFormatToken('E', 0, 0, 'isoWeekday');

// ALIASES

addUnitAlias('day', 'd');
addUnitAlias('weekday', 'e');
addUnitAlias('isoWeekday', 'E');

// PRIORITY
addUnitPriority('day', 11);
addUnitPriority('weekday', 11);
addUnitPriority('isoWeekday', 11);

// PARSING

addRegexToken('d',    match1to2);
addRegexToken('e',    match1to2);
addRegexToken('E',    match1to2);
addRegexToken('dd',   function (isStrict, locale) {
    return locale.weekdaysMinRegex(isStrict);
});
addRegexToken('ddd',   function (isStrict, locale) {
    return locale.weekdaysShortRegex(isStrict);
});
addRegexToken('dddd',   function (isStrict, locale) {
    return locale.weekdaysRegex(isStrict);
});

addWeekParseToken(['dd', 'ddd', 'dddd'], function (input, week, config, token) {
    var weekday = config._locale.weekdaysParse(input, token, config._strict);
    // if we didn't get a weekday name, mark the date as invalid
    if (weekday != null) {
        week.d = weekday;
    } else {
        getParsingFlags(config).invalidWeekday = input;
    }
});

addWeekParseToken(['d', 'e', 'E'], function (input, week, config, token) {
    week[token] = toInt(input);
});

// HELPERS

function parseWeekday(input, locale) {
    if (typeof input !== 'string') {
        return input;
    }

    if (!isNaN(input)) {
        return parseInt(input, 10);
    }

    input = locale.weekdaysParse(input);
    if (typeof input === 'number') {
        return input;
    }

    return null;
}

function parseIsoWeekday(input, locale) {
    if (typeof input === 'string') {
        return locale.weekdaysParse(input) % 7 || 7;
    }
    return isNaN(input) ? null : input;
}

// LOCALES

var defaultLocaleWeekdays = 'Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday'.split('_');
function localeWeekdays (m, format) {
    if (!m) {
        return isArray(this._weekdays) ? this._weekdays :
            this._weekdays['standalone'];
    }
    return isArray(this._weekdays) ? this._weekdays[m.day()] :
        this._weekdays[this._weekdays.isFormat.test(format) ? 'format' : 'standalone'][m.day()];
}

var defaultLocaleWeekdaysShort = 'Sun_Mon_Tue_Wed_Thu_Fri_Sat'.split('_');
function localeWeekdaysShort (m) {
    return (m) ? this._weekdaysShort[m.day()] : this._weekdaysShort;
}

var defaultLocaleWeekdaysMin = 'Su_Mo_Tu_We_Th_Fr_Sa'.split('_');
function localeWeekdaysMin (m) {
    return (m) ? this._weekdaysMin[m.day()] : this._weekdaysMin;
}

function handleStrictParse$1(weekdayName, format, strict) {
    var i, ii, mom, llc = weekdayName.toLocaleLowerCase();
    if (!this._weekdaysParse) {
        this._weekdaysParse = [];
        this._shortWeekdaysParse = [];
        this._minWeekdaysParse = [];

        for (i = 0; i < 7; ++i) {
            mom = createUTC([2000, 1]).day(i);
            this._minWeekdaysParse[i] = this.weekdaysMin(mom, '').toLocaleLowerCase();
            this._shortWeekdaysParse[i] = this.weekdaysShort(mom, '').toLocaleLowerCase();
            this._weekdaysParse[i] = this.weekdays(mom, '').toLocaleLowerCase();
        }
    }

    if (strict) {
        if (format === 'dddd') {
            ii = indexOf$1.call(this._weekdaysParse, llc);
            return ii !== -1 ? ii : null;
        } else if (format === 'ddd') {
            ii = indexOf$1.call(this._shortWeekdaysParse, llc);
            return ii !== -1 ? ii : null;
        } else {
            ii = indexOf$1.call(this._minWeekdaysParse, llc);
            return ii !== -1 ? ii : null;
        }
    } else {
        if (format === 'dddd') {
            ii = indexOf$1.call(this._weekdaysParse, llc);
            if (ii !== -1) {
                return ii;
            }
            ii = indexOf$1.call(this._shortWeekdaysParse, llc);
            if (ii !== -1) {
                return ii;
            }
            ii = indexOf$1.call(this._minWeekdaysParse, llc);
            return ii !== -1 ? ii : null;
        } else if (format === 'ddd') {
            ii = indexOf$1.call(this._shortWeekdaysParse, llc);
            if (ii !== -1) {
                return ii;
            }
            ii = indexOf$1.call(this._weekdaysParse, llc);
            if (ii !== -1) {
                return ii;
            }
            ii = indexOf$1.call(this._minWeekdaysParse, llc);
            return ii !== -1 ? ii : null;
        } else {
            ii = indexOf$1.call(this._minWeekdaysParse, llc);
            if (ii !== -1) {
                return ii;
            }
            ii = indexOf$1.call(this._weekdaysParse, llc);
            if (ii !== -1) {
                return ii;
            }
            ii = indexOf$1.call(this._shortWeekdaysParse, llc);
            return ii !== -1 ? ii : null;
        }
    }
}

function localeWeekdaysParse (weekdayName, format, strict) {
    var i, mom, regex;

    if (this._weekdaysParseExact) {
        return handleStrictParse$1.call(this, weekdayName, format, strict);
    }

    if (!this._weekdaysParse) {
        this._weekdaysParse = [];
        this._minWeekdaysParse = [];
        this._shortWeekdaysParse = [];
        this._fullWeekdaysParse = [];
    }

    for (i = 0; i < 7; i++) {
        // make the regex if we don't have it already

        mom = createUTC([2000, 1]).day(i);
        if (strict && !this._fullWeekdaysParse[i]) {
            this._fullWeekdaysParse[i] = new RegExp('^' + this.weekdays(mom, '').replace('.', '\.?') + '$', 'i');
            this._shortWeekdaysParse[i] = new RegExp('^' + this.weekdaysShort(mom, '').replace('.', '\.?') + '$', 'i');
            this._minWeekdaysParse[i] = new RegExp('^' + this.weekdaysMin(mom, '').replace('.', '\.?') + '$', 'i');
        }
        if (!this._weekdaysParse[i]) {
            regex = '^' + this.weekdays(mom, '') + '|^' + this.weekdaysShort(mom, '') + '|^' + this.weekdaysMin(mom, '');
            this._weekdaysParse[i] = new RegExp(regex.replace('.', ''), 'i');
        }
        // test the regex
        if (strict && format === 'dddd' && this._fullWeekdaysParse[i].test(weekdayName)) {
            return i;
        } else if (strict && format === 'ddd' && this._shortWeekdaysParse[i].test(weekdayName)) {
            return i;
        } else if (strict && format === 'dd' && this._minWeekdaysParse[i].test(weekdayName)) {
            return i;
        } else if (!strict && this._weekdaysParse[i].test(weekdayName)) {
            return i;
        }
    }
}

// MOMENTS

function getSetDayOfWeek (input) {
    if (!this.isValid()) {
        return input != null ? this : NaN;
    }
    var day = this._isUTC ? this._d.getUTCDay() : this._d.getDay();
    if (input != null) {
        input = parseWeekday(input, this.localeData());
        return this.add(input - day, 'd');
    } else {
        return day;
    }
}

function getSetLocaleDayOfWeek (input) {
    if (!this.isValid()) {
        return input != null ? this : NaN;
    }
    var weekday = (this.day() + 7 - this.localeData()._week.dow) % 7;
    return input == null ? weekday : this.add(input - weekday, 'd');
}

function getSetISODayOfWeek (input) {
    if (!this.isValid()) {
        return input != null ? this : NaN;
    }

    // behaves the same as moment#day except
    // as a getter, returns 7 instead of 0 (1-7 range instead of 0-6)
    // as a setter, sunday should belong to the previous week.

    if (input != null) {
        var weekday = parseIsoWeekday(input, this.localeData());
        return this.day(this.day() % 7 ? weekday : weekday - 7);
    } else {
        return this.day() || 7;
    }
}

var defaultWeekdaysRegex = matchWord;
function weekdaysRegex (isStrict) {
    if (this._weekdaysParseExact) {
        if (!hasOwnProp(this, '_weekdaysRegex')) {
            computeWeekdaysParse.call(this);
        }
        if (isStrict) {
            return this._weekdaysStrictRegex;
        } else {
            return this._weekdaysRegex;
        }
    } else {
        if (!hasOwnProp(this, '_weekdaysRegex')) {
            this._weekdaysRegex = defaultWeekdaysRegex;
        }
        return this._weekdaysStrictRegex && isStrict ?
            this._weekdaysStrictRegex : this._weekdaysRegex;
    }
}

var defaultWeekdaysShortRegex = matchWord;
function weekdaysShortRegex (isStrict) {
    if (this._weekdaysParseExact) {
        if (!hasOwnProp(this, '_weekdaysRegex')) {
            computeWeekdaysParse.call(this);
        }
        if (isStrict) {
            return this._weekdaysShortStrictRegex;
        } else {
            return this._weekdaysShortRegex;
        }
    } else {
        if (!hasOwnProp(this, '_weekdaysShortRegex')) {
            this._weekdaysShortRegex = defaultWeekdaysShortRegex;
        }
        return this._weekdaysShortStrictRegex && isStrict ?
            this._weekdaysShortStrictRegex : this._weekdaysShortRegex;
    }
}

var defaultWeekdaysMinRegex = matchWord;
function weekdaysMinRegex (isStrict) {
    if (this._weekdaysParseExact) {
        if (!hasOwnProp(this, '_weekdaysRegex')) {
            computeWeekdaysParse.call(this);
        }
        if (isStrict) {
            return this._weekdaysMinStrictRegex;
        } else {
            return this._weekdaysMinRegex;
        }
    } else {
        if (!hasOwnProp(this, '_weekdaysMinRegex')) {
            this._weekdaysMinRegex = defaultWeekdaysMinRegex;
        }
        return this._weekdaysMinStrictRegex && isStrict ?
            this._weekdaysMinStrictRegex : this._weekdaysMinRegex;
    }
}


function computeWeekdaysParse () {
    function cmpLenRev(a, b) {
        return b.length - a.length;
    }

    var minPieces = [], shortPieces = [], longPieces = [], mixedPieces = [],
        i, mom, minp, shortp, longp;
    for (i = 0; i < 7; i++) {
        // make the regex if we don't have it already
        mom = createUTC([2000, 1]).day(i);
        minp = this.weekdaysMin(mom, '');
        shortp = this.weekdaysShort(mom, '');
        longp = this.weekdays(mom, '');
        minPieces.push(minp);
        shortPieces.push(shortp);
        longPieces.push(longp);
        mixedPieces.push(minp);
        mixedPieces.push(shortp);
        mixedPieces.push(longp);
    }
    // Sorting makes sure if one weekday (or abbr) is a prefix of another it
    // will match the longer piece.
    minPieces.sort(cmpLenRev);
    shortPieces.sort(cmpLenRev);
    longPieces.sort(cmpLenRev);
    mixedPieces.sort(cmpLenRev);
    for (i = 0; i < 7; i++) {
        shortPieces[i] = regexEscape(shortPieces[i]);
        longPieces[i] = regexEscape(longPieces[i]);
        mixedPieces[i] = regexEscape(mixedPieces[i]);
    }

    this._weekdaysRegex = new RegExp('^(' + mixedPieces.join('|') + ')', 'i');
    this._weekdaysShortRegex = this._weekdaysRegex;
    this._weekdaysMinRegex = this._weekdaysRegex;

    this._weekdaysStrictRegex = new RegExp('^(' + longPieces.join('|') + ')', 'i');
    this._weekdaysShortStrictRegex = new RegExp('^(' + shortPieces.join('|') + ')', 'i');
    this._weekdaysMinStrictRegex = new RegExp('^(' + minPieces.join('|') + ')', 'i');
}

// FORMATTING

function hFormat() {
    return this.hours() % 12 || 12;
}

function kFormat() {
    return this.hours() || 24;
}

addFormatToken('H', ['HH', 2], 0, 'hour');
addFormatToken('h', ['hh', 2], 0, hFormat);
addFormatToken('k', ['kk', 2], 0, kFormat);

addFormatToken('hmm', 0, 0, function () {
    return '' + hFormat.apply(this) + zeroFill(this.minutes(), 2);
});

addFormatToken('hmmss', 0, 0, function () {
    return '' + hFormat.apply(this) + zeroFill(this.minutes(), 2) +
        zeroFill(this.seconds(), 2);
});

addFormatToken('Hmm', 0, 0, function () {
    return '' + this.hours() + zeroFill(this.minutes(), 2);
});

addFormatToken('Hmmss', 0, 0, function () {
    return '' + this.hours() + zeroFill(this.minutes(), 2) +
        zeroFill(this.seconds(), 2);
});

function meridiem (token, lowercase) {
    addFormatToken(token, 0, 0, function () {
        return this.localeData().meridiem(this.hours(), this.minutes(), lowercase);
    });
}

meridiem('a', true);
meridiem('A', false);

// ALIASES

addUnitAlias('hour', 'h');

// PRIORITY
addUnitPriority('hour', 13);

// PARSING

function matchMeridiem (isStrict, locale) {
    return locale._meridiemParse;
}

addRegexToken('a',  matchMeridiem);
addRegexToken('A',  matchMeridiem);
addRegexToken('H',  match1to2);
addRegexToken('h',  match1to2);
addRegexToken('k',  match1to2);
addRegexToken('HH', match1to2, match2);
addRegexToken('hh', match1to2, match2);
addRegexToken('kk', match1to2, match2);

addRegexToken('hmm', match3to4);
addRegexToken('hmmss', match5to6);
addRegexToken('Hmm', match3to4);
addRegexToken('Hmmss', match5to6);

addParseToken(['H', 'HH'], HOUR);
addParseToken(['k', 'kk'], function (input, array, config) {
    var kInput = toInt(input);
    array[HOUR] = kInput === 24 ? 0 : kInput;
});
addParseToken(['a', 'A'], function (input, array, config) {
    config._isPm = config._locale.isPM(input);
    config._meridiem = input;
});
addParseToken(['h', 'hh'], function (input, array, config) {
    array[HOUR] = toInt(input);
    getParsingFlags(config).bigHour = true;
});
addParseToken('hmm', function (input, array, config) {
    var pos = input.length - 2;
    array[HOUR] = toInt(input.substr(0, pos));
    array[MINUTE] = toInt(input.substr(pos));
    getParsingFlags(config).bigHour = true;
});
addParseToken('hmmss', function (input, array, config) {
    var pos1 = input.length - 4;
    var pos2 = input.length - 2;
    array[HOUR] = toInt(input.substr(0, pos1));
    array[MINUTE] = toInt(input.substr(pos1, 2));
    array[SECOND] = toInt(input.substr(pos2));
    getParsingFlags(config).bigHour = true;
});
addParseToken('Hmm', function (input, array, config) {
    var pos = input.length - 2;
    array[HOUR] = toInt(input.substr(0, pos));
    array[MINUTE] = toInt(input.substr(pos));
});
addParseToken('Hmmss', function (input, array, config) {
    var pos1 = input.length - 4;
    var pos2 = input.length - 2;
    array[HOUR] = toInt(input.substr(0, pos1));
    array[MINUTE] = toInt(input.substr(pos1, 2));
    array[SECOND] = toInt(input.substr(pos2));
});

// LOCALES

function localeIsPM (input) {
    // IE8 Quirks Mode & IE7 Standards Mode do not allow accessing strings like arrays
    // Using charAt should be more compatible.
    return ((input + '').toLowerCase().charAt(0) === 'p');
}

var defaultLocaleMeridiemParse = /[ap]\.?m?\.?/i;
function localeMeridiem (hours, minutes, isLower) {
    if (hours > 11) {
        return isLower ? 'pm' : 'PM';
    } else {
        return isLower ? 'am' : 'AM';
    }
}


// MOMENTS

// Setting the hour should keep the time, because the user explicitly
// specified which hour he wants. So trying to maintain the same hour (in
// a new timezone) makes sense. Adding/subtracting hours does not follow
// this rule.
var getSetHour = makeGetSet('Hours', true);

// months
// week
// weekdays
// meridiem
var baseConfig = {
    calendar: defaultCalendar,
    longDateFormat: defaultLongDateFormat,
    invalidDate: defaultInvalidDate,
    ordinal: defaultOrdinal,
    dayOfMonthOrdinalParse: defaultDayOfMonthOrdinalParse,
    relativeTime: defaultRelativeTime,

    months: defaultLocaleMonths,
    monthsShort: defaultLocaleMonthsShort,

    week: defaultLocaleWeek,

    weekdays: defaultLocaleWeekdays,
    weekdaysMin: defaultLocaleWeekdaysMin,
    weekdaysShort: defaultLocaleWeekdaysShort,

    meridiemParse: defaultLocaleMeridiemParse
};

// internal storage for locale config files
var locales = {};
var localeFamilies = {};
var globalLocale;

function normalizeLocale(key) {
    return key ? key.toLowerCase().replace('_', '-') : key;
}

// pick the locale from the array
// try ['en-au', 'en-gb'] as 'en-au', 'en-gb', 'en', as in move through the list trying each
// substring from most specific to least, but move to the next array item if it's a more specific variant than the current root
function chooseLocale(names) {
    var i = 0, j, next, locale, split;

    while (i < names.length) {
        split = normalizeLocale(names[i]).split('-');
        j = split.length;
        next = normalizeLocale(names[i + 1]);
        next = next ? next.split('-') : null;
        while (j > 0) {
            locale = loadLocale(split.slice(0, j).join('-'));
            if (locale) {
                return locale;
            }
            if (next && next.length >= j && compareArrays(split, next, true) >= j - 1) {
                //the next array item is better than a shallower substring of this one
                break;
            }
            j--;
        }
        i++;
    }
    return null;
}

function loadLocale(name) {
    var oldLocale = null;
    // TODO: Find a better way to register and load all the locales in Node
    if (!locales[name] && (typeof module !== 'undefined') &&
            module && module.exports) {
        try {
            oldLocale = globalLocale._abbr;
            __webpack_require__(409)("./" + name);
            // because defineLocale currently also sets the global locale, we
            // want to undo that for lazy loaded locales
            getSetGlobalLocale(oldLocale);
        } catch (e) { }
    }
    return locales[name];
}

// This function will load locale and then set the global locale.  If
// no arguments are passed in, it will simply return the current global
// locale key.
function getSetGlobalLocale (key, values) {
    var data;
    if (key) {
        if (isUndefined(values)) {
            data = getLocale(key);
        }
        else {
            data = defineLocale(key, values);
        }

        if (data) {
            // moment.duration._locale = moment._locale = data;
            globalLocale = data;
        }
    }

    return globalLocale._abbr;
}

function defineLocale (name, config) {
    if (config !== null) {
        var parentConfig = baseConfig;
        config.abbr = name;
        if (locales[name] != null) {
            deprecateSimple('defineLocaleOverride',
                    'use moment.updateLocale(localeName, config) to change ' +
                    'an existing locale. moment.defineLocale(localeName, ' +
                    'config) should only be used for creating a new locale ' +
                    'See http://momentjs.com/guides/#/warnings/define-locale/ for more info.');
            parentConfig = locales[name]._config;
        } else if (config.parentLocale != null) {
            if (locales[config.parentLocale] != null) {
                parentConfig = locales[config.parentLocale]._config;
            } else {
                if (!localeFamilies[config.parentLocale]) {
                    localeFamilies[config.parentLocale] = [];
                }
                localeFamilies[config.parentLocale].push({
                    name: name,
                    config: config
                });
                return null;
            }
        }
        locales[name] = new Locale(mergeConfigs(parentConfig, config));

        if (localeFamilies[name]) {
            localeFamilies[name].forEach(function (x) {
                defineLocale(x.name, x.config);
            });
        }

        // backwards compat for now: also set the locale
        // make sure we set the locale AFTER all child locales have been
        // created, so we won't end up with the child locale set.
        getSetGlobalLocale(name);


        return locales[name];
    } else {
        // useful for testing
        delete locales[name];
        return null;
    }
}

function updateLocale(name, config) {
    if (config != null) {
        var locale, parentConfig = baseConfig;
        // MERGE
        if (locales[name] != null) {
            parentConfig = locales[name]._config;
        }
        config = mergeConfigs(parentConfig, config);
        locale = new Locale(config);
        locale.parentLocale = locales[name];
        locales[name] = locale;

        // backwards compat for now: also set the locale
        getSetGlobalLocale(name);
    } else {
        // pass null for config to unupdate, useful for tests
        if (locales[name] != null) {
            if (locales[name].parentLocale != null) {
                locales[name] = locales[name].parentLocale;
            } else if (locales[name] != null) {
                delete locales[name];
            }
        }
    }
    return locales[name];
}

// returns locale data
function getLocale (key) {
    var locale;

    if (key && key._locale && key._locale._abbr) {
        key = key._locale._abbr;
    }

    if (!key) {
        return globalLocale;
    }

    if (!isArray(key)) {
        //short-circuit everything else
        locale = loadLocale(key);
        if (locale) {
            return locale;
        }
        key = [key];
    }

    return chooseLocale(key);
}

function listLocales() {
    return keys$1(locales);
}

function checkOverflow (m) {
    var overflow;
    var a = m._a;

    if (a && getParsingFlags(m).overflow === -2) {
        overflow =
            a[MONTH]       < 0 || a[MONTH]       > 11  ? MONTH :
            a[DATE]        < 1 || a[DATE]        > daysInMonth(a[YEAR], a[MONTH]) ? DATE :
            a[HOUR]        < 0 || a[HOUR]        > 24 || (a[HOUR] === 24 && (a[MINUTE] !== 0 || a[SECOND] !== 0 || a[MILLISECOND] !== 0)) ? HOUR :
            a[MINUTE]      < 0 || a[MINUTE]      > 59  ? MINUTE :
            a[SECOND]      < 0 || a[SECOND]      > 59  ? SECOND :
            a[MILLISECOND] < 0 || a[MILLISECOND] > 999 ? MILLISECOND :
            -1;

        if (getParsingFlags(m)._overflowDayOfYear && (overflow < YEAR || overflow > DATE)) {
            overflow = DATE;
        }
        if (getParsingFlags(m)._overflowWeeks && overflow === -1) {
            overflow = WEEK;
        }
        if (getParsingFlags(m)._overflowWeekday && overflow === -1) {
            overflow = WEEKDAY;
        }

        getParsingFlags(m).overflow = overflow;
    }

    return m;
}

// iso 8601 regex
// 0000-00-00 0000-W00 or 0000-W00-0 + T + 00 or 00:00 or 00:00:00 or 00:00:00.000 + +00:00 or +0000 or +00)
var extendedIsoRegex = /^\s*((?:[+-]\d{6}|\d{4})-(?:\d\d-\d\d|W\d\d-\d|W\d\d|\d\d\d|\d\d))(?:(T| )(\d\d(?::\d\d(?::\d\d(?:[.,]\d+)?)?)?)([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?$/;
var basicIsoRegex = /^\s*((?:[+-]\d{6}|\d{4})(?:\d\d\d\d|W\d\d\d|W\d\d|\d\d\d|\d\d))(?:(T| )(\d\d(?:\d\d(?:\d\d(?:[.,]\d+)?)?)?)([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?$/;

var tzRegex = /Z|[+-]\d\d(?::?\d\d)?/;

var isoDates = [
    ['YYYYYY-MM-DD', /[+-]\d{6}-\d\d-\d\d/],
    ['YYYY-MM-DD', /\d{4}-\d\d-\d\d/],
    ['GGGG-[W]WW-E', /\d{4}-W\d\d-\d/],
    ['GGGG-[W]WW', /\d{4}-W\d\d/, false],
    ['YYYY-DDD', /\d{4}-\d{3}/],
    ['YYYY-MM', /\d{4}-\d\d/, false],
    ['YYYYYYMMDD', /[+-]\d{10}/],
    ['YYYYMMDD', /\d{8}/],
    // YYYYMM is NOT allowed by the standard
    ['GGGG[W]WWE', /\d{4}W\d{3}/],
    ['GGGG[W]WW', /\d{4}W\d{2}/, false],
    ['YYYYDDD', /\d{7}/]
];

// iso time formats and regexes
var isoTimes = [
    ['HH:mm:ss.SSSS', /\d\d:\d\d:\d\d\.\d+/],
    ['HH:mm:ss,SSSS', /\d\d:\d\d:\d\d,\d+/],
    ['HH:mm:ss', /\d\d:\d\d:\d\d/],
    ['HH:mm', /\d\d:\d\d/],
    ['HHmmss.SSSS', /\d\d\d\d\d\d\.\d+/],
    ['HHmmss,SSSS', /\d\d\d\d\d\d,\d+/],
    ['HHmmss', /\d\d\d\d\d\d/],
    ['HHmm', /\d\d\d\d/],
    ['HH', /\d\d/]
];

var aspNetJsonRegex = /^\/?Date\((\-?\d+)/i;

// date from iso format
function configFromISO(config) {
    var i, l,
        string = config._i,
        match = extendedIsoRegex.exec(string) || basicIsoRegex.exec(string),
        allowTime, dateFormat, timeFormat, tzFormat;

    if (match) {
        getParsingFlags(config).iso = true;

        for (i = 0, l = isoDates.length; i < l; i++) {
            if (isoDates[i][1].exec(match[1])) {
                dateFormat = isoDates[i][0];
                allowTime = isoDates[i][2] !== false;
                break;
            }
        }
        if (dateFormat == null) {
            config._isValid = false;
            return;
        }
        if (match[3]) {
            for (i = 0, l = isoTimes.length; i < l; i++) {
                if (isoTimes[i][1].exec(match[3])) {
                    // match[2] should be 'T' or space
                    timeFormat = (match[2] || ' ') + isoTimes[i][0];
                    break;
                }
            }
            if (timeFormat == null) {
                config._isValid = false;
                return;
            }
        }
        if (!allowTime && timeFormat != null) {
            config._isValid = false;
            return;
        }
        if (match[4]) {
            if (tzRegex.exec(match[4])) {
                tzFormat = 'Z';
            } else {
                config._isValid = false;
                return;
            }
        }
        config._f = dateFormat + (timeFormat || '') + (tzFormat || '');
        configFromStringAndFormat(config);
    } else {
        config._isValid = false;
    }
}

// RFC 2822 regex: For details see https://tools.ietf.org/html/rfc2822#section-3.3
var basicRfcRegex = /^((?:Mon|Tue|Wed|Thu|Fri|Sat|Sun),?\s)?(\d?\d\s(?:Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\s(?:\d\d)?\d\d\s)(\d\d:\d\d)(\:\d\d)?(\s(?:UT|GMT|[ECMP][SD]T|[A-IK-Za-ik-z]|[+-]\d{4}))$/;

// date and time from ref 2822 format
function configFromRFC2822(config) {
    var string, match, dayFormat,
        dateFormat, timeFormat, tzFormat;
    var timezones = {
        ' GMT': ' +0000',
        ' EDT': ' -0400',
        ' EST': ' -0500',
        ' CDT': ' -0500',
        ' CST': ' -0600',
        ' MDT': ' -0600',
        ' MST': ' -0700',
        ' PDT': ' -0700',
        ' PST': ' -0800'
    };
    var military = 'YXWVUTSRQPONZABCDEFGHIKLM';
    var timezone, timezoneIndex;

    string = config._i
        .replace(/\([^\)]*\)|[\n\t]/g, ' ') // Remove comments and folding whitespace
        .replace(/(\s\s+)/g, ' ') // Replace multiple-spaces with a single space
        .replace(/^\s|\s$/g, ''); // Remove leading and trailing spaces
    match = basicRfcRegex.exec(string);

    if (match) {
        dayFormat = match[1] ? 'ddd' + ((match[1].length === 5) ? ', ' : ' ') : '';
        dateFormat = 'D MMM ' + ((match[2].length > 10) ? 'YYYY ' : 'YY ');
        timeFormat = 'HH:mm' + (match[4] ? ':ss' : '');

        // TODO: Replace the vanilla JS Date object with an indepentent day-of-week check.
        if (match[1]) { // day of week given
            var momentDate = new Date(match[2]);
            var momentDay = ['Sun','Mon','Tue','Wed','Thu','Fri','Sat'][momentDate.getDay()];

            if (match[1].substr(0,3) !== momentDay) {
                getParsingFlags(config).weekdayMismatch = true;
                config._isValid = false;
                return;
            }
        }

        switch (match[5].length) {
            case 2: // military
                if (timezoneIndex === 0) {
                    timezone = ' +0000';
                } else {
                    timezoneIndex = military.indexOf(match[5][1].toUpperCase()) - 12;
                    timezone = ((timezoneIndex < 0) ? ' -' : ' +') +
                        (('' + timezoneIndex).replace(/^-?/, '0')).match(/..$/)[0] + '00';
                }
                break;
            case 4: // Zone
                timezone = timezones[match[5]];
                break;
            default: // UT or +/-9999
                timezone = timezones[' GMT'];
        }
        match[5] = timezone;
        config._i = match.splice(1).join('');
        tzFormat = ' ZZ';
        config._f = dayFormat + dateFormat + timeFormat + tzFormat;
        configFromStringAndFormat(config);
        getParsingFlags(config).rfc2822 = true;
    } else {
        config._isValid = false;
    }
}

// date from iso format or fallback
function configFromString(config) {
    var matched = aspNetJsonRegex.exec(config._i);

    if (matched !== null) {
        config._d = new Date(+matched[1]);
        return;
    }

    configFromISO(config);
    if (config._isValid === false) {
        delete config._isValid;
    } else {
        return;
    }

    configFromRFC2822(config);
    if (config._isValid === false) {
        delete config._isValid;
    } else {
        return;
    }

    // Final attempt, use Input Fallback
    hooks.createFromInputFallback(config);
}

hooks.createFromInputFallback = deprecate(
    'value provided is not in a recognized RFC2822 or ISO format. moment construction falls back to js Date(), ' +
    'which is not reliable across all browsers and versions. Non RFC2822/ISO date formats are ' +
    'discouraged and will be removed in an upcoming major release. Please refer to ' +
    'http://momentjs.com/guides/#/warnings/js-date/ for more info.',
    function (config) {
        config._d = new Date(config._i + (config._useUTC ? ' UTC' : ''));
    }
);

// Pick the first defined of two or three arguments.
function defaults(a, b, c) {
    if (a != null) {
        return a;
    }
    if (b != null) {
        return b;
    }
    return c;
}

function currentDateArray(config) {
    // hooks is actually the exported moment object
    var nowValue = new Date(hooks.now());
    if (config._useUTC) {
        return [nowValue.getUTCFullYear(), nowValue.getUTCMonth(), nowValue.getUTCDate()];
    }
    return [nowValue.getFullYear(), nowValue.getMonth(), nowValue.getDate()];
}

// convert an array to a date.
// the array should mirror the parameters below
// note: all values past the year are optional and will default to the lowest possible value.
// [year, month, day , hour, minute, second, millisecond]
function configFromArray (config) {
    var i, date, input = [], currentDate, yearToUse;

    if (config._d) {
        return;
    }

    currentDate = currentDateArray(config);

    //compute day of the year from weeks and weekdays
    if (config._w && config._a[DATE] == null && config._a[MONTH] == null) {
        dayOfYearFromWeekInfo(config);
    }

    //if the day of the year is set, figure out what it is
    if (config._dayOfYear != null) {
        yearToUse = defaults(config._a[YEAR], currentDate[YEAR]);

        if (config._dayOfYear > daysInYear(yearToUse) || config._dayOfYear === 0) {
            getParsingFlags(config)._overflowDayOfYear = true;
        }

        date = createUTCDate(yearToUse, 0, config._dayOfYear);
        config._a[MONTH] = date.getUTCMonth();
        config._a[DATE] = date.getUTCDate();
    }

    // Default to current date.
    // * if no year, month, day of month are given, default to today
    // * if day of month is given, default month and year
    // * if month is given, default only year
    // * if year is given, don't default anything
    for (i = 0; i < 3 && config._a[i] == null; ++i) {
        config._a[i] = input[i] = currentDate[i];
    }

    // Zero out whatever was not defaulted, including time
    for (; i < 7; i++) {
        config._a[i] = input[i] = (config._a[i] == null) ? (i === 2 ? 1 : 0) : config._a[i];
    }

    // Check for 24:00:00.000
    if (config._a[HOUR] === 24 &&
            config._a[MINUTE] === 0 &&
            config._a[SECOND] === 0 &&
            config._a[MILLISECOND] === 0) {
        config._nextDay = true;
        config._a[HOUR] = 0;
    }

    config._d = (config._useUTC ? createUTCDate : createDate).apply(null, input);
    // Apply timezone offset from input. The actual utcOffset can be changed
    // with parseZone.
    if (config._tzm != null) {
        config._d.setUTCMinutes(config._d.getUTCMinutes() - config._tzm);
    }

    if (config._nextDay) {
        config._a[HOUR] = 24;
    }
}

function dayOfYearFromWeekInfo(config) {
    var w, weekYear, week, weekday, dow, doy, temp, weekdayOverflow;

    w = config._w;
    if (w.GG != null || w.W != null || w.E != null) {
        dow = 1;
        doy = 4;

        // TODO: We need to take the current isoWeekYear, but that depends on
        // how we interpret now (local, utc, fixed offset). So create
        // a now version of current config (take local/utc/offset flags, and
        // create now).
        weekYear = defaults(w.GG, config._a[YEAR], weekOfYear(createLocal(), 1, 4).year);
        week = defaults(w.W, 1);
        weekday = defaults(w.E, 1);
        if (weekday < 1 || weekday > 7) {
            weekdayOverflow = true;
        }
    } else {
        dow = config._locale._week.dow;
        doy = config._locale._week.doy;

        var curWeek = weekOfYear(createLocal(), dow, doy);

        weekYear = defaults(w.gg, config._a[YEAR], curWeek.year);

        // Default to current week.
        week = defaults(w.w, curWeek.week);

        if (w.d != null) {
            // weekday -- low day numbers are considered next week
            weekday = w.d;
            if (weekday < 0 || weekday > 6) {
                weekdayOverflow = true;
            }
        } else if (w.e != null) {
            // local weekday -- counting starts from begining of week
            weekday = w.e + dow;
            if (w.e < 0 || w.e > 6) {
                weekdayOverflow = true;
            }
        } else {
            // default to begining of week
            weekday = dow;
        }
    }
    if (week < 1 || week > weeksInYear(weekYear, dow, doy)) {
        getParsingFlags(config)._overflowWeeks = true;
    } else if (weekdayOverflow != null) {
        getParsingFlags(config)._overflowWeekday = true;
    } else {
        temp = dayOfYearFromWeeks(weekYear, week, weekday, dow, doy);
        config._a[YEAR] = temp.year;
        config._dayOfYear = temp.dayOfYear;
    }
}

// constant that refers to the ISO standard
hooks.ISO_8601 = function () {};

// constant that refers to the RFC 2822 form
hooks.RFC_2822 = function () {};

// date from string and format string
function configFromStringAndFormat(config) {
    // TODO: Move this to another part of the creation flow to prevent circular deps
    if (config._f === hooks.ISO_8601) {
        configFromISO(config);
        return;
    }
    if (config._f === hooks.RFC_2822) {
        configFromRFC2822(config);
        return;
    }
    config._a = [];
    getParsingFlags(config).empty = true;

    // This array is used to make a Date, either with `new Date` or `Date.UTC`
    var string = '' + config._i,
        i, parsedInput, tokens, token, skipped,
        stringLength = string.length,
        totalParsedInputLength = 0;

    tokens = expandFormat(config._f, config._locale).match(formattingTokens) || [];

    for (i = 0; i < tokens.length; i++) {
        token = tokens[i];
        parsedInput = (string.match(getParseRegexForToken(token, config)) || [])[0];
        // console.log('token', token, 'parsedInput', parsedInput,
        //         'regex', getParseRegexForToken(token, config));
        if (parsedInput) {
            skipped = string.substr(0, string.indexOf(parsedInput));
            if (skipped.length > 0) {
                getParsingFlags(config).unusedInput.push(skipped);
            }
            string = string.slice(string.indexOf(parsedInput) + parsedInput.length);
            totalParsedInputLength += parsedInput.length;
        }
        // don't parse if it's not a known token
        if (formatTokenFunctions[token]) {
            if (parsedInput) {
                getParsingFlags(config).empty = false;
            }
            else {
                getParsingFlags(config).unusedTokens.push(token);
            }
            addTimeToArrayFromToken(token, parsedInput, config);
        }
        else if (config._strict && !parsedInput) {
            getParsingFlags(config).unusedTokens.push(token);
        }
    }

    // add remaining unparsed input length to the string
    getParsingFlags(config).charsLeftOver = stringLength - totalParsedInputLength;
    if (string.length > 0) {
        getParsingFlags(config).unusedInput.push(string);
    }

    // clear _12h flag if hour is <= 12
    if (config._a[HOUR] <= 12 &&
        getParsingFlags(config).bigHour === true &&
        config._a[HOUR] > 0) {
        getParsingFlags(config).bigHour = undefined;
    }

    getParsingFlags(config).parsedDateParts = config._a.slice(0);
    getParsingFlags(config).meridiem = config._meridiem;
    // handle meridiem
    config._a[HOUR] = meridiemFixWrap(config._locale, config._a[HOUR], config._meridiem);

    configFromArray(config);
    checkOverflow(config);
}


function meridiemFixWrap (locale, hour, meridiem) {
    var isPm;

    if (meridiem == null) {
        // nothing to do
        return hour;
    }
    if (locale.meridiemHour != null) {
        return locale.meridiemHour(hour, meridiem);
    } else if (locale.isPM != null) {
        // Fallback
        isPm = locale.isPM(meridiem);
        if (isPm && hour < 12) {
            hour += 12;
        }
        if (!isPm && hour === 12) {
            hour = 0;
        }
        return hour;
    } else {
        // this is not supposed to happen
        return hour;
    }
}

// date from string and array of format strings
function configFromStringAndArray(config) {
    var tempConfig,
        bestMoment,

        scoreToBeat,
        i,
        currentScore;

    if (config._f.length === 0) {
        getParsingFlags(config).invalidFormat = true;
        config._d = new Date(NaN);
        return;
    }

    for (i = 0; i < config._f.length; i++) {
        currentScore = 0;
        tempConfig = copyConfig({}, config);
        if (config._useUTC != null) {
            tempConfig._useUTC = config._useUTC;
        }
        tempConfig._f = config._f[i];
        configFromStringAndFormat(tempConfig);

        if (!isValid(tempConfig)) {
            continue;
        }

        // if there is any input that was not parsed add a penalty for that format
        currentScore += getParsingFlags(tempConfig).charsLeftOver;

        //or tokens
        currentScore += getParsingFlags(tempConfig).unusedTokens.length * 10;

        getParsingFlags(tempConfig).score = currentScore;

        if (scoreToBeat == null || currentScore < scoreToBeat) {
            scoreToBeat = currentScore;
            bestMoment = tempConfig;
        }
    }

    extend(config, bestMoment || tempConfig);
}

function configFromObject(config) {
    if (config._d) {
        return;
    }

    var i = normalizeObjectUnits(config._i);
    config._a = map([i.year, i.month, i.day || i.date, i.hour, i.minute, i.second, i.millisecond], function (obj) {
        return obj && parseInt(obj, 10);
    });

    configFromArray(config);
}

function createFromConfig (config) {
    var res = new Moment(checkOverflow(prepareConfig(config)));
    if (res._nextDay) {
        // Adding is smart enough around DST
        res.add(1, 'd');
        res._nextDay = undefined;
    }

    return res;
}

function prepareConfig (config) {
    var input = config._i,
        format = config._f;

    config._locale = config._locale || getLocale(config._l);

    if (input === null || (format === undefined && input === '')) {
        return createInvalid({nullInput: true});
    }

    if (typeof input === 'string') {
        config._i = input = config._locale.preparse(input);
    }

    if (isMoment(input)) {
        return new Moment(checkOverflow(input));
    } else if (isDate(input)) {
        config._d = input;
    } else if (isArray(format)) {
        configFromStringAndArray(config);
    } else if (format) {
        configFromStringAndFormat(config);
    }  else {
        configFromInput(config);
    }

    if (!isValid(config)) {
        config._d = null;
    }

    return config;
}

function configFromInput(config) {
    var input = config._i;
    if (isUndefined(input)) {
        config._d = new Date(hooks.now());
    } else if (isDate(input)) {
        config._d = new Date(input.valueOf());
    } else if (typeof input === 'string') {
        configFromString(config);
    } else if (isArray(input)) {
        config._a = map(input.slice(0), function (obj) {
            return parseInt(obj, 10);
        });
        configFromArray(config);
    } else if (isObject(input)) {
        configFromObject(config);
    } else if (isNumber(input)) {
        // from milliseconds
        config._d = new Date(input);
    } else {
        hooks.createFromInputFallback(config);
    }
}

function createLocalOrUTC (input, format, locale, strict, isUTC) {
    var c = {};

    if (locale === true || locale === false) {
        strict = locale;
        locale = undefined;
    }

    if ((isObject(input) && isObjectEmpty(input)) ||
            (isArray(input) && input.length === 0)) {
        input = undefined;
    }
    // object construction must be done this way.
    // https://github.com/moment/moment/issues/1423
    c._isAMomentObject = true;
    c._useUTC = c._isUTC = isUTC;
    c._l = locale;
    c._i = input;
    c._f = format;
    c._strict = strict;

    return createFromConfig(c);
}

function createLocal (input, format, locale, strict) {
    return createLocalOrUTC(input, format, locale, strict, false);
}

var prototypeMin = deprecate(
    'moment().min is deprecated, use moment.max instead. http://momentjs.com/guides/#/warnings/min-max/',
    function () {
        var other = createLocal.apply(null, arguments);
        if (this.isValid() && other.isValid()) {
            return other < this ? this : other;
        } else {
            return createInvalid();
        }
    }
);

var prototypeMax = deprecate(
    'moment().max is deprecated, use moment.min instead. http://momentjs.com/guides/#/warnings/min-max/',
    function () {
        var other = createLocal.apply(null, arguments);
        if (this.isValid() && other.isValid()) {
            return other > this ? this : other;
        } else {
            return createInvalid();
        }
    }
);

// Pick a moment m from moments so that m[fn](other) is true for all
// other. This relies on the function fn to be transitive.
//
// moments should either be an array of moment objects or an array, whose
// first element is an array of moment objects.
function pickBy(fn, moments) {
    var res, i;
    if (moments.length === 1 && isArray(moments[0])) {
        moments = moments[0];
    }
    if (!moments.length) {
        return createLocal();
    }
    res = moments[0];
    for (i = 1; i < moments.length; ++i) {
        if (!moments[i].isValid() || moments[i][fn](res)) {
            res = moments[i];
        }
    }
    return res;
}

// TODO: Use [].sort instead?
function min () {
    var args = [].slice.call(arguments, 0);

    return pickBy('isBefore', args);
}

function max () {
    var args = [].slice.call(arguments, 0);

    return pickBy('isAfter', args);
}

var now = function () {
    return Date.now ? Date.now() : +(new Date());
};

var ordering = ['year', 'quarter', 'month', 'week', 'day', 'hour', 'minute', 'second', 'millisecond'];

function isDurationValid(m) {
    for (var key in m) {
        if (!(ordering.indexOf(key) !== -1 && (m[key] == null || !isNaN(m[key])))) {
            return false;
        }
    }

    var unitHasDecimal = false;
    for (var i = 0; i < ordering.length; ++i) {
        if (m[ordering[i]]) {
            if (unitHasDecimal) {
                return false; // only allow non-integers for smallest unit
            }
            if (parseFloat(m[ordering[i]]) !== toInt(m[ordering[i]])) {
                unitHasDecimal = true;
            }
        }
    }

    return true;
}

function isValid$1() {
    return this._isValid;
}

function createInvalid$1() {
    return createDuration(NaN);
}

function Duration (duration) {
    var normalizedInput = normalizeObjectUnits(duration),
        years = normalizedInput.year || 0,
        quarters = normalizedInput.quarter || 0,
        months = normalizedInput.month || 0,
        weeks = normalizedInput.week || 0,
        days = normalizedInput.day || 0,
        hours = normalizedInput.hour || 0,
        minutes = normalizedInput.minute || 0,
        seconds = normalizedInput.second || 0,
        milliseconds = normalizedInput.millisecond || 0;

    this._isValid = isDurationValid(normalizedInput);

    // representation for dateAddRemove
    this._milliseconds = +milliseconds +
        seconds * 1e3 + // 1000
        minutes * 6e4 + // 1000 * 60
        hours * 1000 * 60 * 60; //using 1000 * 60 * 60 instead of 36e5 to avoid floating point rounding errors https://github.com/moment/moment/issues/2978
    // Because of dateAddRemove treats 24 hours as different from a
    // day when working around DST, we need to store them separately
    this._days = +days +
        weeks * 7;
    // It is impossible translate months into days without knowing
    // which months you are are talking about, so we have to store
    // it separately.
    this._months = +months +
        quarters * 3 +
        years * 12;

    this._data = {};

    this._locale = getLocale();

    this._bubble();
}

function isDuration (obj) {
    return obj instanceof Duration;
}

function absRound (number) {
    if (number < 0) {
        return Math.round(-1 * number) * -1;
    } else {
        return Math.round(number);
    }
}

// FORMATTING

function offset (token, separator) {
    addFormatToken(token, 0, 0, function () {
        var offset = this.utcOffset();
        var sign = '+';
        if (offset < 0) {
            offset = -offset;
            sign = '-';
        }
        return sign + zeroFill(~~(offset / 60), 2) + separator + zeroFill(~~(offset) % 60, 2);
    });
}

offset('Z', ':');
offset('ZZ', '');

// PARSING

addRegexToken('Z',  matchShortOffset);
addRegexToken('ZZ', matchShortOffset);
addParseToken(['Z', 'ZZ'], function (input, array, config) {
    config._useUTC = true;
    config._tzm = offsetFromString(matchShortOffset, input);
});

// HELPERS

// timezone chunker
// '+10:00' > ['10',  '00']
// '-1530'  > ['-15', '30']
var chunkOffset = /([\+\-]|\d\d)/gi;

function offsetFromString(matcher, string) {
    var matches = (string || '').match(matcher);

    if (matches === null) {
        return null;
    }

    var chunk   = matches[matches.length - 1] || [];
    var parts   = (chunk + '').match(chunkOffset) || ['-', 0, 0];
    var minutes = +(parts[1] * 60) + toInt(parts[2]);

    return minutes === 0 ?
      0 :
      parts[0] === '+' ? minutes : -minutes;
}

// Return a moment from input, that is local/utc/zone equivalent to model.
function cloneWithOffset(input, model) {
    var res, diff;
    if (model._isUTC) {
        res = model.clone();
        diff = (isMoment(input) || isDate(input) ? input.valueOf() : createLocal(input).valueOf()) - res.valueOf();
        // Use low-level api, because this fn is low-level api.
        res._d.setTime(res._d.valueOf() + diff);
        hooks.updateOffset(res, false);
        return res;
    } else {
        return createLocal(input).local();
    }
}

function getDateOffset (m) {
    // On Firefox.24 Date#getTimezoneOffset returns a floating point.
    // https://github.com/moment/moment/pull/1871
    return -Math.round(m._d.getTimezoneOffset() / 15) * 15;
}

// HOOKS

// This function will be called whenever a moment is mutated.
// It is intended to keep the offset in sync with the timezone.
hooks.updateOffset = function () {};

// MOMENTS

// keepLocalTime = true means only change the timezone, without
// affecting the local hour. So 5:31:26 +0300 --[utcOffset(2, true)]-->
// 5:31:26 +0200 It is possible that 5:31:26 doesn't exist with offset
// +0200, so we adjust the time as needed, to be valid.
//
// Keeping the time actually adds/subtracts (one hour)
// from the actual represented time. That is why we call updateOffset
// a second time. In case it wants us to change the offset again
// _changeInProgress == true case, then we have to adjust, because
// there is no such time in the given timezone.
function getSetOffset (input, keepLocalTime, keepMinutes) {
    var offset = this._offset || 0,
        localAdjust;
    if (!this.isValid()) {
        return input != null ? this : NaN;
    }
    if (input != null) {
        if (typeof input === 'string') {
            input = offsetFromString(matchShortOffset, input);
            if (input === null) {
                return this;
            }
        } else if (Math.abs(input) < 16 && !keepMinutes) {
            input = input * 60;
        }
        if (!this._isUTC && keepLocalTime) {
            localAdjust = getDateOffset(this);
        }
        this._offset = input;
        this._isUTC = true;
        if (localAdjust != null) {
            this.add(localAdjust, 'm');
        }
        if (offset !== input) {
            if (!keepLocalTime || this._changeInProgress) {
                addSubtract(this, createDuration(input - offset, 'm'), 1, false);
            } else if (!this._changeInProgress) {
                this._changeInProgress = true;
                hooks.updateOffset(this, true);
                this._changeInProgress = null;
            }
        }
        return this;
    } else {
        return this._isUTC ? offset : getDateOffset(this);
    }
}

function getSetZone (input, keepLocalTime) {
    if (input != null) {
        if (typeof input !== 'string') {
            input = -input;
        }

        this.utcOffset(input, keepLocalTime);

        return this;
    } else {
        return -this.utcOffset();
    }
}

function setOffsetToUTC (keepLocalTime) {
    return this.utcOffset(0, keepLocalTime);
}

function setOffsetToLocal (keepLocalTime) {
    if (this._isUTC) {
        this.utcOffset(0, keepLocalTime);
        this._isUTC = false;

        if (keepLocalTime) {
            this.subtract(getDateOffset(this), 'm');
        }
    }
    return this;
}

function setOffsetToParsedOffset () {
    if (this._tzm != null) {
        this.utcOffset(this._tzm, false, true);
    } else if (typeof this._i === 'string') {
        var tZone = offsetFromString(matchOffset, this._i);
        if (tZone != null) {
            this.utcOffset(tZone);
        }
        else {
            this.utcOffset(0, true);
        }
    }
    return this;
}

function hasAlignedHourOffset (input) {
    if (!this.isValid()) {
        return false;
    }
    input = input ? createLocal(input).utcOffset() : 0;

    return (this.utcOffset() - input) % 60 === 0;
}

function isDaylightSavingTime () {
    return (
        this.utcOffset() > this.clone().month(0).utcOffset() ||
        this.utcOffset() > this.clone().month(5).utcOffset()
    );
}

function isDaylightSavingTimeShifted () {
    if (!isUndefined(this._isDSTShifted)) {
        return this._isDSTShifted;
    }

    var c = {};

    copyConfig(c, this);
    c = prepareConfig(c);

    if (c._a) {
        var other = c._isUTC ? createUTC(c._a) : createLocal(c._a);
        this._isDSTShifted = this.isValid() &&
            compareArrays(c._a, other.toArray()) > 0;
    } else {
        this._isDSTShifted = false;
    }

    return this._isDSTShifted;
}

function isLocal () {
    return this.isValid() ? !this._isUTC : false;
}

function isUtcOffset () {
    return this.isValid() ? this._isUTC : false;
}

function isUtc () {
    return this.isValid() ? this._isUTC && this._offset === 0 : false;
}

// ASP.NET json date format regex
var aspNetRegex = /^(\-)?(?:(\d*)[. ])?(\d+)\:(\d+)(?:\:(\d+)(\.\d*)?)?$/;

// from http://docs.closure-library.googlecode.com/git/closure_goog_date_date.js.source.html
// somewhat more in line with 4.4.3.2 2004 spec, but allows decimal anywhere
// and further modified to allow for strings containing both week and day
var isoRegex = /^(-)?P(?:(-?[0-9,.]*)Y)?(?:(-?[0-9,.]*)M)?(?:(-?[0-9,.]*)W)?(?:(-?[0-9,.]*)D)?(?:T(?:(-?[0-9,.]*)H)?(?:(-?[0-9,.]*)M)?(?:(-?[0-9,.]*)S)?)?$/;

function createDuration (input, key) {
    var duration = input,
        // matching against regexp is expensive, do it on demand
        match = null,
        sign,
        ret,
        diffRes;

    if (isDuration(input)) {
        duration = {
            ms : input._milliseconds,
            d  : input._days,
            M  : input._months
        };
    } else if (isNumber(input)) {
        duration = {};
        if (key) {
            duration[key] = input;
        } else {
            duration.milliseconds = input;
        }
    } else if (!!(match = aspNetRegex.exec(input))) {
        sign = (match[1] === '-') ? -1 : 1;
        duration = {
            y  : 0,
            d  : toInt(match[DATE])                         * sign,
            h  : toInt(match[HOUR])                         * sign,
            m  : toInt(match[MINUTE])                       * sign,
            s  : toInt(match[SECOND])                       * sign,
            ms : toInt(absRound(match[MILLISECOND] * 1000)) * sign // the millisecond decimal point is included in the match
        };
    } else if (!!(match = isoRegex.exec(input))) {
        sign = (match[1] === '-') ? -1 : 1;
        duration = {
            y : parseIso(match[2], sign),
            M : parseIso(match[3], sign),
            w : parseIso(match[4], sign),
            d : parseIso(match[5], sign),
            h : parseIso(match[6], sign),
            m : parseIso(match[7], sign),
            s : parseIso(match[8], sign)
        };
    } else if (duration == null) {// checks for null or undefined
        duration = {};
    } else if (typeof duration === 'object' && ('from' in duration || 'to' in duration)) {
        diffRes = momentsDifference(createLocal(duration.from), createLocal(duration.to));

        duration = {};
        duration.ms = diffRes.milliseconds;
        duration.M = diffRes.months;
    }

    ret = new Duration(duration);

    if (isDuration(input) && hasOwnProp(input, '_locale')) {
        ret._locale = input._locale;
    }

    return ret;
}

createDuration.fn = Duration.prototype;
createDuration.invalid = createInvalid$1;

function parseIso (inp, sign) {
    // We'd normally use ~~inp for this, but unfortunately it also
    // converts floats to ints.
    // inp may be undefined, so careful calling replace on it.
    var res = inp && parseFloat(inp.replace(',', '.'));
    // apply sign while we're at it
    return (isNaN(res) ? 0 : res) * sign;
}

function positiveMomentsDifference(base, other) {
    var res = {milliseconds: 0, months: 0};

    res.months = other.month() - base.month() +
        (other.year() - base.year()) * 12;
    if (base.clone().add(res.months, 'M').isAfter(other)) {
        --res.months;
    }

    res.milliseconds = +other - +(base.clone().add(res.months, 'M'));

    return res;
}

function momentsDifference(base, other) {
    var res;
    if (!(base.isValid() && other.isValid())) {
        return {milliseconds: 0, months: 0};
    }

    other = cloneWithOffset(other, base);
    if (base.isBefore(other)) {
        res = positiveMomentsDifference(base, other);
    } else {
        res = positiveMomentsDifference(other, base);
        res.milliseconds = -res.milliseconds;
        res.months = -res.months;
    }

    return res;
}

// TODO: remove 'name' arg after deprecation is removed
function createAdder(direction, name) {
    return function (val, period) {
        var dur, tmp;
        //invert the arguments, but complain about it
        if (period !== null && !isNaN(+period)) {
            deprecateSimple(name, 'moment().' + name  + '(period, number) is deprecated. Please use moment().' + name + '(number, period). ' +
            'See http://momentjs.com/guides/#/warnings/add-inverted-param/ for more info.');
            tmp = val; val = period; period = tmp;
        }

        val = typeof val === 'string' ? +val : val;
        dur = createDuration(val, period);
        addSubtract(this, dur, direction);
        return this;
    };
}

function addSubtract (mom, duration, isAdding, updateOffset) {
    var milliseconds = duration._milliseconds,
        days = absRound(duration._days),
        months = absRound(duration._months);

    if (!mom.isValid()) {
        // No op
        return;
    }

    updateOffset = updateOffset == null ? true : updateOffset;

    if (milliseconds) {
        mom._d.setTime(mom._d.valueOf() + milliseconds * isAdding);
    }
    if (days) {
        set$1(mom, 'Date', get(mom, 'Date') + days * isAdding);
    }
    if (months) {
        setMonth(mom, get(mom, 'Month') + months * isAdding);
    }
    if (updateOffset) {
        hooks.updateOffset(mom, days || months);
    }
}

var add      = createAdder(1, 'add');
var subtract = createAdder(-1, 'subtract');

function getCalendarFormat(myMoment, now) {
    var diff = myMoment.diff(now, 'days', true);
    return diff < -6 ? 'sameElse' :
            diff < -1 ? 'lastWeek' :
            diff < 0 ? 'lastDay' :
            diff < 1 ? 'sameDay' :
            diff < 2 ? 'nextDay' :
            diff < 7 ? 'nextWeek' : 'sameElse';
}

function calendar$1 (time, formats) {
    // We want to compare the start of today, vs this.
    // Getting start-of-today depends on whether we're local/utc/offset or not.
    var now = time || createLocal(),
        sod = cloneWithOffset(now, this).startOf('day'),
        format = hooks.calendarFormat(this, sod) || 'sameElse';

    var output = formats && (isFunction(formats[format]) ? formats[format].call(this, now) : formats[format]);

    return this.format(output || this.localeData().calendar(format, this, createLocal(now)));
}

function clone () {
    return new Moment(this);
}

function isAfter (input, units) {
    var localInput = isMoment(input) ? input : createLocal(input);
    if (!(this.isValid() && localInput.isValid())) {
        return false;
    }
    units = normalizeUnits(!isUndefined(units) ? units : 'millisecond');
    if (units === 'millisecond') {
        return this.valueOf() > localInput.valueOf();
    } else {
        return localInput.valueOf() < this.clone().startOf(units).valueOf();
    }
}

function isBefore (input, units) {
    var localInput = isMoment(input) ? input : createLocal(input);
    if (!(this.isValid() && localInput.isValid())) {
        return false;
    }
    units = normalizeUnits(!isUndefined(units) ? units : 'millisecond');
    if (units === 'millisecond') {
        return this.valueOf() < localInput.valueOf();
    } else {
        return this.clone().endOf(units).valueOf() < localInput.valueOf();
    }
}

function isBetween (from, to, units, inclusivity) {
    inclusivity = inclusivity || '()';
    return (inclusivity[0] === '(' ? this.isAfter(from, units) : !this.isBefore(from, units)) &&
        (inclusivity[1] === ')' ? this.isBefore(to, units) : !this.isAfter(to, units));
}

function isSame (input, units) {
    var localInput = isMoment(input) ? input : createLocal(input),
        inputMs;
    if (!(this.isValid() && localInput.isValid())) {
        return false;
    }
    units = normalizeUnits(units || 'millisecond');
    if (units === 'millisecond') {
        return this.valueOf() === localInput.valueOf();
    } else {
        inputMs = localInput.valueOf();
        return this.clone().startOf(units).valueOf() <= inputMs && inputMs <= this.clone().endOf(units).valueOf();
    }
}

function isSameOrAfter (input, units) {
    return this.isSame(input, units) || this.isAfter(input,units);
}

function isSameOrBefore (input, units) {
    return this.isSame(input, units) || this.isBefore(input,units);
}

function diff (input, units, asFloat) {
    var that,
        zoneDelta,
        delta, output;

    if (!this.isValid()) {
        return NaN;
    }

    that = cloneWithOffset(input, this);

    if (!that.isValid()) {
        return NaN;
    }

    zoneDelta = (that.utcOffset() - this.utcOffset()) * 6e4;

    units = normalizeUnits(units);

    if (units === 'year' || units === 'month' || units === 'quarter') {
        output = monthDiff(this, that);
        if (units === 'quarter') {
            output = output / 3;
        } else if (units === 'year') {
            output = output / 12;
        }
    } else {
        delta = this - that;
        output = units === 'second' ? delta / 1e3 : // 1000
            units === 'minute' ? delta / 6e4 : // 1000 * 60
            units === 'hour' ? delta / 36e5 : // 1000 * 60 * 60
            units === 'day' ? (delta - zoneDelta) / 864e5 : // 1000 * 60 * 60 * 24, negate dst
            units === 'week' ? (delta - zoneDelta) / 6048e5 : // 1000 * 60 * 60 * 24 * 7, negate dst
            delta;
    }
    return asFloat ? output : absFloor(output);
}

function monthDiff (a, b) {
    // difference in months
    var wholeMonthDiff = ((b.year() - a.year()) * 12) + (b.month() - a.month()),
        // b is in (anchor - 1 month, anchor + 1 month)
        anchor = a.clone().add(wholeMonthDiff, 'months'),
        anchor2, adjust;

    if (b - anchor < 0) {
        anchor2 = a.clone().add(wholeMonthDiff - 1, 'months');
        // linear across the month
        adjust = (b - anchor) / (anchor - anchor2);
    } else {
        anchor2 = a.clone().add(wholeMonthDiff + 1, 'months');
        // linear across the month
        adjust = (b - anchor) / (anchor2 - anchor);
    }

    //check for negative zero, return zero if negative zero
    return -(wholeMonthDiff + adjust) || 0;
}

hooks.defaultFormat = 'YYYY-MM-DDTHH:mm:ssZ';
hooks.defaultFormatUtc = 'YYYY-MM-DDTHH:mm:ss[Z]';

function toString () {
    return this.clone().locale('en').format('ddd MMM DD YYYY HH:mm:ss [GMT]ZZ');
}

function toISOString() {
    if (!this.isValid()) {
        return null;
    }
    var m = this.clone().utc();
    if (m.year() < 0 || m.year() > 9999) {
        return formatMoment(m, 'YYYYYY-MM-DD[T]HH:mm:ss.SSS[Z]');
    }
    if (isFunction(Date.prototype.toISOString)) {
        // native implementation is ~50x faster, use it when we can
        return this.toDate().toISOString();
    }
    return formatMoment(m, 'YYYY-MM-DD[T]HH:mm:ss.SSS[Z]');
}

/**
 * Return a human readable representation of a moment that can
 * also be evaluated to get a new moment which is the same
 *
 * @link https://nodejs.org/dist/latest/docs/api/util.html#util_custom_inspect_function_on_objects
 */
function inspect () {
    if (!this.isValid()) {
        return 'moment.invalid(/* ' + this._i + ' */)';
    }
    var func = 'moment';
    var zone = '';
    if (!this.isLocal()) {
        func = this.utcOffset() === 0 ? 'moment.utc' : 'moment.parseZone';
        zone = 'Z';
    }
    var prefix = '[' + func + '("]';
    var year = (0 <= this.year() && this.year() <= 9999) ? 'YYYY' : 'YYYYYY';
    var datetime = '-MM-DD[T]HH:mm:ss.SSS';
    var suffix = zone + '[")]';

    return this.format(prefix + year + datetime + suffix);
}

function format (inputString) {
    if (!inputString) {
        inputString = this.isUtc() ? hooks.defaultFormatUtc : hooks.defaultFormat;
    }
    var output = formatMoment(this, inputString);
    return this.localeData().postformat(output);
}

function from (time, withoutSuffix) {
    if (this.isValid() &&
            ((isMoment(time) && time.isValid()) ||
             createLocal(time).isValid())) {
        return createDuration({to: this, from: time}).locale(this.locale()).humanize(!withoutSuffix);
    } else {
        return this.localeData().invalidDate();
    }
}

function fromNow (withoutSuffix) {
    return this.from(createLocal(), withoutSuffix);
}

function to (time, withoutSuffix) {
    if (this.isValid() &&
            ((isMoment(time) && time.isValid()) ||
             createLocal(time).isValid())) {
        return createDuration({from: this, to: time}).locale(this.locale()).humanize(!withoutSuffix);
    } else {
        return this.localeData().invalidDate();
    }
}

function toNow (withoutSuffix) {
    return this.to(createLocal(), withoutSuffix);
}

// If passed a locale key, it will set the locale for this
// instance.  Otherwise, it will return the locale configuration
// variables for this instance.
function locale (key) {
    var newLocaleData;

    if (key === undefined) {
        return this._locale._abbr;
    } else {
        newLocaleData = getLocale(key);
        if (newLocaleData != null) {
            this._locale = newLocaleData;
        }
        return this;
    }
}

var lang = deprecate(
    'moment().lang() is deprecated. Instead, use moment().localeData() to get the language configuration. Use moment().locale() to change languages.',
    function (key) {
        if (key === undefined) {
            return this.localeData();
        } else {
            return this.locale(key);
        }
    }
);

function localeData () {
    return this._locale;
}

function startOf (units) {
    units = normalizeUnits(units);
    // the following switch intentionally omits break keywords
    // to utilize falling through the cases.
    switch (units) {
        case 'year':
            this.month(0);
            /* falls through */
        case 'quarter':
        case 'month':
            this.date(1);
            /* falls through */
        case 'week':
        case 'isoWeek':
        case 'day':
        case 'date':
            this.hours(0);
            /* falls through */
        case 'hour':
            this.minutes(0);
            /* falls through */
        case 'minute':
            this.seconds(0);
            /* falls through */
        case 'second':
            this.milliseconds(0);
    }

    // weeks are a special case
    if (units === 'week') {
        this.weekday(0);
    }
    if (units === 'isoWeek') {
        this.isoWeekday(1);
    }

    // quarters are also special
    if (units === 'quarter') {
        this.month(Math.floor(this.month() / 3) * 3);
    }

    return this;
}

function endOf (units) {
    units = normalizeUnits(units);
    if (units === undefined || units === 'millisecond') {
        return this;
    }

    // 'date' is an alias for 'day', so it should be considered as such.
    if (units === 'date') {
        units = 'day';
    }

    return this.startOf(units).add(1, (units === 'isoWeek' ? 'week' : units)).subtract(1, 'ms');
}

function valueOf () {
    return this._d.valueOf() - ((this._offset || 0) * 60000);
}

function unix () {
    return Math.floor(this.valueOf() / 1000);
}

function toDate () {
    return new Date(this.valueOf());
}

function toArray () {
    var m = this;
    return [m.year(), m.month(), m.date(), m.hour(), m.minute(), m.second(), m.millisecond()];
}

function toObject () {
    var m = this;
    return {
        years: m.year(),
        months: m.month(),
        date: m.date(),
        hours: m.hours(),
        minutes: m.minutes(),
        seconds: m.seconds(),
        milliseconds: m.milliseconds()
    };
}

function toJSON () {
    // new Date(NaN).toJSON() === null
    return this.isValid() ? this.toISOString() : null;
}

function isValid$2 () {
    return isValid(this);
}

function parsingFlags () {
    return extend({}, getParsingFlags(this));
}

function invalidAt () {
    return getParsingFlags(this).overflow;
}

function creationData() {
    return {
        input: this._i,
        format: this._f,
        locale: this._locale,
        isUTC: this._isUTC,
        strict: this._strict
    };
}

// FORMATTING

addFormatToken(0, ['gg', 2], 0, function () {
    return this.weekYear() % 100;
});

addFormatToken(0, ['GG', 2], 0, function () {
    return this.isoWeekYear() % 100;
});

function addWeekYearFormatToken (token, getter) {
    addFormatToken(0, [token, token.length], 0, getter);
}

addWeekYearFormatToken('gggg',     'weekYear');
addWeekYearFormatToken('ggggg',    'weekYear');
addWeekYearFormatToken('GGGG',  'isoWeekYear');
addWeekYearFormatToken('GGGGG', 'isoWeekYear');

// ALIASES

addUnitAlias('weekYear', 'gg');
addUnitAlias('isoWeekYear', 'GG');

// PRIORITY

addUnitPriority('weekYear', 1);
addUnitPriority('isoWeekYear', 1);


// PARSING

addRegexToken('G',      matchSigned);
addRegexToken('g',      matchSigned);
addRegexToken('GG',     match1to2, match2);
addRegexToken('gg',     match1to2, match2);
addRegexToken('GGGG',   match1to4, match4);
addRegexToken('gggg',   match1to4, match4);
addRegexToken('GGGGG',  match1to6, match6);
addRegexToken('ggggg',  match1to6, match6);

addWeekParseToken(['gggg', 'ggggg', 'GGGG', 'GGGGG'], function (input, week, config, token) {
    week[token.substr(0, 2)] = toInt(input);
});

addWeekParseToken(['gg', 'GG'], function (input, week, config, token) {
    week[token] = hooks.parseTwoDigitYear(input);
});

// MOMENTS

function getSetWeekYear (input) {
    return getSetWeekYearHelper.call(this,
            input,
            this.week(),
            this.weekday(),
            this.localeData()._week.dow,
            this.localeData()._week.doy);
}

function getSetISOWeekYear (input) {
    return getSetWeekYearHelper.call(this,
            input, this.isoWeek(), this.isoWeekday(), 1, 4);
}

function getISOWeeksInYear () {
    return weeksInYear(this.year(), 1, 4);
}

function getWeeksInYear () {
    var weekInfo = this.localeData()._week;
    return weeksInYear(this.year(), weekInfo.dow, weekInfo.doy);
}

function getSetWeekYearHelper(input, week, weekday, dow, doy) {
    var weeksTarget;
    if (input == null) {
        return weekOfYear(this, dow, doy).year;
    } else {
        weeksTarget = weeksInYear(input, dow, doy);
        if (week > weeksTarget) {
            week = weeksTarget;
        }
        return setWeekAll.call(this, input, week, weekday, dow, doy);
    }
}

function setWeekAll(weekYear, week, weekday, dow, doy) {
    var dayOfYearData = dayOfYearFromWeeks(weekYear, week, weekday, dow, doy),
        date = createUTCDate(dayOfYearData.year, 0, dayOfYearData.dayOfYear);

    this.year(date.getUTCFullYear());
    this.month(date.getUTCMonth());
    this.date(date.getUTCDate());
    return this;
}

// FORMATTING

addFormatToken('Q', 0, 'Qo', 'quarter');

// ALIASES

addUnitAlias('quarter', 'Q');

// PRIORITY

addUnitPriority('quarter', 7);

// PARSING

addRegexToken('Q', match1);
addParseToken('Q', function (input, array) {
    array[MONTH] = (toInt(input) - 1) * 3;
});

// MOMENTS

function getSetQuarter (input) {
    return input == null ? Math.ceil((this.month() + 1) / 3) : this.month((input - 1) * 3 + this.month() % 3);
}

// FORMATTING

addFormatToken('D', ['DD', 2], 'Do', 'date');

// ALIASES

addUnitAlias('date', 'D');

// PRIOROITY
addUnitPriority('date', 9);

// PARSING

addRegexToken('D',  match1to2);
addRegexToken('DD', match1to2, match2);
addRegexToken('Do', function (isStrict, locale) {
    // TODO: Remove "ordinalParse" fallback in next major release.
    return isStrict ?
      (locale._dayOfMonthOrdinalParse || locale._ordinalParse) :
      locale._dayOfMonthOrdinalParseLenient;
});

addParseToken(['D', 'DD'], DATE);
addParseToken('Do', function (input, array) {
    array[DATE] = toInt(input.match(match1to2)[0], 10);
});

// MOMENTS

var getSetDayOfMonth = makeGetSet('Date', true);

// FORMATTING

addFormatToken('DDD', ['DDDD', 3], 'DDDo', 'dayOfYear');

// ALIASES

addUnitAlias('dayOfYear', 'DDD');

// PRIORITY
addUnitPriority('dayOfYear', 4);

// PARSING

addRegexToken('DDD',  match1to3);
addRegexToken('DDDD', match3);
addParseToken(['DDD', 'DDDD'], function (input, array, config) {
    config._dayOfYear = toInt(input);
});

// HELPERS

// MOMENTS

function getSetDayOfYear (input) {
    var dayOfYear = Math.round((this.clone().startOf('day') - this.clone().startOf('year')) / 864e5) + 1;
    return input == null ? dayOfYear : this.add((input - dayOfYear), 'd');
}

// FORMATTING

addFormatToken('m', ['mm', 2], 0, 'minute');

// ALIASES

addUnitAlias('minute', 'm');

// PRIORITY

addUnitPriority('minute', 14);

// PARSING

addRegexToken('m',  match1to2);
addRegexToken('mm', match1to2, match2);
addParseToken(['m', 'mm'], MINUTE);

// MOMENTS

var getSetMinute = makeGetSet('Minutes', false);

// FORMATTING

addFormatToken('s', ['ss', 2], 0, 'second');

// ALIASES

addUnitAlias('second', 's');

// PRIORITY

addUnitPriority('second', 15);

// PARSING

addRegexToken('s',  match1to2);
addRegexToken('ss', match1to2, match2);
addParseToken(['s', 'ss'], SECOND);

// MOMENTS

var getSetSecond = makeGetSet('Seconds', false);

// FORMATTING

addFormatToken('S', 0, 0, function () {
    return ~~(this.millisecond() / 100);
});

addFormatToken(0, ['SS', 2], 0, function () {
    return ~~(this.millisecond() / 10);
});

addFormatToken(0, ['SSS', 3], 0, 'millisecond');
addFormatToken(0, ['SSSS', 4], 0, function () {
    return this.millisecond() * 10;
});
addFormatToken(0, ['SSSSS', 5], 0, function () {
    return this.millisecond() * 100;
});
addFormatToken(0, ['SSSSSS', 6], 0, function () {
    return this.millisecond() * 1000;
});
addFormatToken(0, ['SSSSSSS', 7], 0, function () {
    return this.millisecond() * 10000;
});
addFormatToken(0, ['SSSSSSSS', 8], 0, function () {
    return this.millisecond() * 100000;
});
addFormatToken(0, ['SSSSSSSSS', 9], 0, function () {
    return this.millisecond() * 1000000;
});


// ALIASES

addUnitAlias('millisecond', 'ms');

// PRIORITY

addUnitPriority('millisecond', 16);

// PARSING

addRegexToken('S',    match1to3, match1);
addRegexToken('SS',   match1to3, match2);
addRegexToken('SSS',  match1to3, match3);

var token;
for (token = 'SSSS'; token.length <= 9; token += 'S') {
    addRegexToken(token, matchUnsigned);
}

function parseMs(input, array) {
    array[MILLISECOND] = toInt(('0.' + input) * 1000);
}

for (token = 'S'; token.length <= 9; token += 'S') {
    addParseToken(token, parseMs);
}
// MOMENTS

var getSetMillisecond = makeGetSet('Milliseconds', false);

// FORMATTING

addFormatToken('z',  0, 0, 'zoneAbbr');
addFormatToken('zz', 0, 0, 'zoneName');

// MOMENTS

function getZoneAbbr () {
    return this._isUTC ? 'UTC' : '';
}

function getZoneName () {
    return this._isUTC ? 'Coordinated Universal Time' : '';
}

var proto = Moment.prototype;

proto.add               = add;
proto.calendar          = calendar$1;
proto.clone             = clone;
proto.diff              = diff;
proto.endOf             = endOf;
proto.format            = format;
proto.from              = from;
proto.fromNow           = fromNow;
proto.to                = to;
proto.toNow             = toNow;
proto.get               = stringGet;
proto.invalidAt         = invalidAt;
proto.isAfter           = isAfter;
proto.isBefore          = isBefore;
proto.isBetween         = isBetween;
proto.isSame            = isSame;
proto.isSameOrAfter     = isSameOrAfter;
proto.isSameOrBefore    = isSameOrBefore;
proto.isValid           = isValid$2;
proto.lang              = lang;
proto.locale            = locale;
proto.localeData        = localeData;
proto.max               = prototypeMax;
proto.min               = prototypeMin;
proto.parsingFlags      = parsingFlags;
proto.set               = stringSet;
proto.startOf           = startOf;
proto.subtract          = subtract;
proto.toArray           = toArray;
proto.toObject          = toObject;
proto.toDate            = toDate;
proto.toISOString       = toISOString;
proto.inspect           = inspect;
proto.toJSON            = toJSON;
proto.toString          = toString;
proto.unix              = unix;
proto.valueOf           = valueOf;
proto.creationData      = creationData;

// Year
proto.year       = getSetYear;
proto.isLeapYear = getIsLeapYear;

// Week Year
proto.weekYear    = getSetWeekYear;
proto.isoWeekYear = getSetISOWeekYear;

// Quarter
proto.quarter = proto.quarters = getSetQuarter;

// Month
proto.month       = getSetMonth;
proto.daysInMonth = getDaysInMonth;

// Week
proto.week           = proto.weeks        = getSetWeek;
proto.isoWeek        = proto.isoWeeks     = getSetISOWeek;
proto.weeksInYear    = getWeeksInYear;
proto.isoWeeksInYear = getISOWeeksInYear;

// Day
proto.date       = getSetDayOfMonth;
proto.day        = proto.days             = getSetDayOfWeek;
proto.weekday    = getSetLocaleDayOfWeek;
proto.isoWeekday = getSetISODayOfWeek;
proto.dayOfYear  = getSetDayOfYear;

// Hour
proto.hour = proto.hours = getSetHour;

// Minute
proto.minute = proto.minutes = getSetMinute;

// Second
proto.second = proto.seconds = getSetSecond;

// Millisecond
proto.millisecond = proto.milliseconds = getSetMillisecond;

// Offset
proto.utcOffset            = getSetOffset;
proto.utc                  = setOffsetToUTC;
proto.local                = setOffsetToLocal;
proto.parseZone            = setOffsetToParsedOffset;
proto.hasAlignedHourOffset = hasAlignedHourOffset;
proto.isDST                = isDaylightSavingTime;
proto.isLocal              = isLocal;
proto.isUtcOffset          = isUtcOffset;
proto.isUtc                = isUtc;
proto.isUTC                = isUtc;

// Timezone
proto.zoneAbbr = getZoneAbbr;
proto.zoneName = getZoneName;

// Deprecations
proto.dates  = deprecate('dates accessor is deprecated. Use date instead.', getSetDayOfMonth);
proto.months = deprecate('months accessor is deprecated. Use month instead', getSetMonth);
proto.years  = deprecate('years accessor is deprecated. Use year instead', getSetYear);
proto.zone   = deprecate('moment().zone is deprecated, use moment().utcOffset instead. http://momentjs.com/guides/#/warnings/zone/', getSetZone);
proto.isDSTShifted = deprecate('isDSTShifted is deprecated. See http://momentjs.com/guides/#/warnings/dst-shifted/ for more information', isDaylightSavingTimeShifted);

function createUnix (input) {
    return createLocal(input * 1000);
}

function createInZone () {
    return createLocal.apply(null, arguments).parseZone();
}

function preParsePostFormat (string) {
    return string;
}

var proto$1 = Locale.prototype;

proto$1.calendar        = calendar;
proto$1.longDateFormat  = longDateFormat;
proto$1.invalidDate     = invalidDate;
proto$1.ordinal         = ordinal;
proto$1.preparse        = preParsePostFormat;
proto$1.postformat      = preParsePostFormat;
proto$1.relativeTime    = relativeTime;
proto$1.pastFuture      = pastFuture;
proto$1.set             = set;

// Month
proto$1.months            =        localeMonths;
proto$1.monthsShort       =        localeMonthsShort;
proto$1.monthsParse       =        localeMonthsParse;
proto$1.monthsRegex       = monthsRegex;
proto$1.monthsShortRegex  = monthsShortRegex;

// Week
proto$1.week = localeWeek;
proto$1.firstDayOfYear = localeFirstDayOfYear;
proto$1.firstDayOfWeek = localeFirstDayOfWeek;

// Day of Week
proto$1.weekdays       =        localeWeekdays;
proto$1.weekdaysMin    =        localeWeekdaysMin;
proto$1.weekdaysShort  =        localeWeekdaysShort;
proto$1.weekdaysParse  =        localeWeekdaysParse;

proto$1.weekdaysRegex       =        weekdaysRegex;
proto$1.weekdaysShortRegex  =        weekdaysShortRegex;
proto$1.weekdaysMinRegex    =        weekdaysMinRegex;

// Hours
proto$1.isPM = localeIsPM;
proto$1.meridiem = localeMeridiem;

function get$1 (format, index, field, setter) {
    var locale = getLocale();
    var utc = createUTC().set(setter, index);
    return locale[field](utc, format);
}

function listMonthsImpl (format, index, field) {
    if (isNumber(format)) {
        index = format;
        format = undefined;
    }

    format = format || '';

    if (index != null) {
        return get$1(format, index, field, 'month');
    }

    var i;
    var out = [];
    for (i = 0; i < 12; i++) {
        out[i] = get$1(format, i, field, 'month');
    }
    return out;
}

// ()
// (5)
// (fmt, 5)
// (fmt)
// (true)
// (true, 5)
// (true, fmt, 5)
// (true, fmt)
function listWeekdaysImpl (localeSorted, format, index, field) {
    if (typeof localeSorted === 'boolean') {
        if (isNumber(format)) {
            index = format;
            format = undefined;
        }

        format = format || '';
    } else {
        format = localeSorted;
        index = format;
        localeSorted = false;

        if (isNumber(format)) {
            index = format;
            format = undefined;
        }

        format = format || '';
    }

    var locale = getLocale(),
        shift = localeSorted ? locale._week.dow : 0;

    if (index != null) {
        return get$1(format, (index + shift) % 7, field, 'day');
    }

    var i;
    var out = [];
    for (i = 0; i < 7; i++) {
        out[i] = get$1(format, (i + shift) % 7, field, 'day');
    }
    return out;
}

function listMonths (format, index) {
    return listMonthsImpl(format, index, 'months');
}

function listMonthsShort (format, index) {
    return listMonthsImpl(format, index, 'monthsShort');
}

function listWeekdays (localeSorted, format, index) {
    return listWeekdaysImpl(localeSorted, format, index, 'weekdays');
}

function listWeekdaysShort (localeSorted, format, index) {
    return listWeekdaysImpl(localeSorted, format, index, 'weekdaysShort');
}

function listWeekdaysMin (localeSorted, format, index) {
    return listWeekdaysImpl(localeSorted, format, index, 'weekdaysMin');
}

getSetGlobalLocale('en', {
    dayOfMonthOrdinalParse: /\d{1,2}(th|st|nd|rd)/,
    ordinal : function (number) {
        var b = number % 10,
            output = (toInt(number % 100 / 10) === 1) ? 'th' :
            (b === 1) ? 'st' :
            (b === 2) ? 'nd' :
            (b === 3) ? 'rd' : 'th';
        return number + output;
    }
});

// Side effect imports
hooks.lang = deprecate('moment.lang is deprecated. Use moment.locale instead.', getSetGlobalLocale);
hooks.langData = deprecate('moment.langData is deprecated. Use moment.localeData instead.', getLocale);

var mathAbs = Math.abs;

function abs () {
    var data           = this._data;

    this._milliseconds = mathAbs(this._milliseconds);
    this._days         = mathAbs(this._days);
    this._months       = mathAbs(this._months);

    data.milliseconds  = mathAbs(data.milliseconds);
    data.seconds       = mathAbs(data.seconds);
    data.minutes       = mathAbs(data.minutes);
    data.hours         = mathAbs(data.hours);
    data.months        = mathAbs(data.months);
    data.years         = mathAbs(data.years);

    return this;
}

function addSubtract$1 (duration, input, value, direction) {
    var other = createDuration(input, value);

    duration._milliseconds += direction * other._milliseconds;
    duration._days         += direction * other._days;
    duration._months       += direction * other._months;

    return duration._bubble();
}

// supports only 2.0-style add(1, 's') or add(duration)
function add$1 (input, value) {
    return addSubtract$1(this, input, value, 1);
}

// supports only 2.0-style subtract(1, 's') or subtract(duration)
function subtract$1 (input, value) {
    return addSubtract$1(this, input, value, -1);
}

function absCeil (number) {
    if (number < 0) {
        return Math.floor(number);
    } else {
        return Math.ceil(number);
    }
}

function bubble () {
    var milliseconds = this._milliseconds;
    var days         = this._days;
    var months       = this._months;
    var data         = this._data;
    var seconds, minutes, hours, years, monthsFromDays;

    // if we have a mix of positive and negative values, bubble down first
    // check: https://github.com/moment/moment/issues/2166
    if (!((milliseconds >= 0 && days >= 0 && months >= 0) ||
            (milliseconds <= 0 && days <= 0 && months <= 0))) {
        milliseconds += absCeil(monthsToDays(months) + days) * 864e5;
        days = 0;
        months = 0;
    }

    // The following code bubbles up values, see the tests for
    // examples of what that means.
    data.milliseconds = milliseconds % 1000;

    seconds           = absFloor(milliseconds / 1000);
    data.seconds      = seconds % 60;

    minutes           = absFloor(seconds / 60);
    data.minutes      = minutes % 60;

    hours             = absFloor(minutes / 60);
    data.hours        = hours % 24;

    days += absFloor(hours / 24);

    // convert days to months
    monthsFromDays = absFloor(daysToMonths(days));
    months += monthsFromDays;
    days -= absCeil(monthsToDays(monthsFromDays));

    // 12 months -> 1 year
    years = absFloor(months / 12);
    months %= 12;

    data.days   = days;
    data.months = months;
    data.years  = years;

    return this;
}

function daysToMonths (days) {
    // 400 years have 146097 days (taking into account leap year rules)
    // 400 years have 12 months === 4800
    return days * 4800 / 146097;
}

function monthsToDays (months) {
    // the reverse of daysToMonths
    return months * 146097 / 4800;
}

function as (units) {
    if (!this.isValid()) {
        return NaN;
    }
    var days;
    var months;
    var milliseconds = this._milliseconds;

    units = normalizeUnits(units);

    if (units === 'month' || units === 'year') {
        days   = this._days   + milliseconds / 864e5;
        months = this._months + daysToMonths(days);
        return units === 'month' ? months : months / 12;
    } else {
        // handle milliseconds separately because of floating point math errors (issue #1867)
        days = this._days + Math.round(monthsToDays(this._months));
        switch (units) {
            case 'week'   : return days / 7     + milliseconds / 6048e5;
            case 'day'    : return days         + milliseconds / 864e5;
            case 'hour'   : return days * 24    + milliseconds / 36e5;
            case 'minute' : return days * 1440  + milliseconds / 6e4;
            case 'second' : return days * 86400 + milliseconds / 1000;
            // Math.floor prevents floating point math errors here
            case 'millisecond': return Math.floor(days * 864e5) + milliseconds;
            default: throw new Error('Unknown unit ' + units);
        }
    }
}

// TODO: Use this.as('ms')?
function valueOf$1 () {
    if (!this.isValid()) {
        return NaN;
    }
    return (
        this._milliseconds +
        this._days * 864e5 +
        (this._months % 12) * 2592e6 +
        toInt(this._months / 12) * 31536e6
    );
}

function makeAs (alias) {
    return function () {
        return this.as(alias);
    };
}

var asMilliseconds = makeAs('ms');
var asSeconds      = makeAs('s');
var asMinutes      = makeAs('m');
var asHours        = makeAs('h');
var asDays         = makeAs('d');
var asWeeks        = makeAs('w');
var asMonths       = makeAs('M');
var asYears        = makeAs('y');

function get$2 (units) {
    units = normalizeUnits(units);
    return this.isValid() ? this[units + 's']() : NaN;
}

function makeGetter(name) {
    return function () {
        return this.isValid() ? this._data[name] : NaN;
    };
}

var milliseconds = makeGetter('milliseconds');
var seconds      = makeGetter('seconds');
var minutes      = makeGetter('minutes');
var hours        = makeGetter('hours');
var days         = makeGetter('days');
var months       = makeGetter('months');
var years        = makeGetter('years');

function weeks () {
    return absFloor(this.days() / 7);
}

var round = Math.round;
var thresholds = {
    ss: 44,         // a few seconds to seconds
    s : 45,         // seconds to minute
    m : 45,         // minutes to hour
    h : 22,         // hours to day
    d : 26,         // days to month
    M : 11          // months to year
};

// helper function for moment.fn.from, moment.fn.fromNow, and moment.duration.fn.humanize
function substituteTimeAgo(string, number, withoutSuffix, isFuture, locale) {
    return locale.relativeTime(number || 1, !!withoutSuffix, string, isFuture);
}

function relativeTime$1 (posNegDuration, withoutSuffix, locale) {
    var duration = createDuration(posNegDuration).abs();
    var seconds  = round(duration.as('s'));
    var minutes  = round(duration.as('m'));
    var hours    = round(duration.as('h'));
    var days     = round(duration.as('d'));
    var months   = round(duration.as('M'));
    var years    = round(duration.as('y'));

    var a = seconds <= thresholds.ss && ['s', seconds]  ||
            seconds < thresholds.s   && ['ss', seconds] ||
            minutes <= 1             && ['m']           ||
            minutes < thresholds.m   && ['mm', minutes] ||
            hours   <= 1             && ['h']           ||
            hours   < thresholds.h   && ['hh', hours]   ||
            days    <= 1             && ['d']           ||
            days    < thresholds.d   && ['dd', days]    ||
            months  <= 1             && ['M']           ||
            months  < thresholds.M   && ['MM', months]  ||
            years   <= 1             && ['y']           || ['yy', years];

    a[2] = withoutSuffix;
    a[3] = +posNegDuration > 0;
    a[4] = locale;
    return substituteTimeAgo.apply(null, a);
}

// This function allows you to set the rounding function for relative time strings
function getSetRelativeTimeRounding (roundingFunction) {
    if (roundingFunction === undefined) {
        return round;
    }
    if (typeof(roundingFunction) === 'function') {
        round = roundingFunction;
        return true;
    }
    return false;
}

// This function allows you to set a threshold for relative time strings
function getSetRelativeTimeThreshold (threshold, limit) {
    if (thresholds[threshold] === undefined) {
        return false;
    }
    if (limit === undefined) {
        return thresholds[threshold];
    }
    thresholds[threshold] = limit;
    if (threshold === 's') {
        thresholds.ss = limit - 1;
    }
    return true;
}

function humanize (withSuffix) {
    if (!this.isValid()) {
        return this.localeData().invalidDate();
    }

    var locale = this.localeData();
    var output = relativeTime$1(this, !withSuffix, locale);

    if (withSuffix) {
        output = locale.pastFuture(+this, output);
    }

    return locale.postformat(output);
}

var abs$1 = Math.abs;

function toISOString$1() {
    // for ISO strings we do not use the normal bubbling rules:
    //  * milliseconds bubble up until they become hours
    //  * days do not bubble at all
    //  * months bubble up until they become years
    // This is because there is no context-free conversion between hours and days
    // (think of clock changes)
    // and also not between days and months (28-31 days per month)
    if (!this.isValid()) {
        return this.localeData().invalidDate();
    }

    var seconds = abs$1(this._milliseconds) / 1000;
    var days         = abs$1(this._days);
    var months       = abs$1(this._months);
    var minutes, hours, years;

    // 3600 seconds -> 60 minutes -> 1 hour
    minutes           = absFloor(seconds / 60);
    hours             = absFloor(minutes / 60);
    seconds %= 60;
    minutes %= 60;

    // 12 months -> 1 year
    years  = absFloor(months / 12);
    months %= 12;


    // inspired by https://github.com/dordille/moment-isoduration/blob/master/moment.isoduration.js
    var Y = years;
    var M = months;
    var D = days;
    var h = hours;
    var m = minutes;
    var s = seconds;
    var total = this.asSeconds();

    if (!total) {
        // this is the same as C#'s (Noda) and python (isodate)...
        // but not other JS (goog.date)
        return 'P0D';
    }

    return (total < 0 ? '-' : '') +
        'P' +
        (Y ? Y + 'Y' : '') +
        (M ? M + 'M' : '') +
        (D ? D + 'D' : '') +
        ((h || m || s) ? 'T' : '') +
        (h ? h + 'H' : '') +
        (m ? m + 'M' : '') +
        (s ? s + 'S' : '');
}

var proto$2 = Duration.prototype;

proto$2.isValid        = isValid$1;
proto$2.abs            = abs;
proto$2.add            = add$1;
proto$2.subtract       = subtract$1;
proto$2.as             = as;
proto$2.asMilliseconds = asMilliseconds;
proto$2.asSeconds      = asSeconds;
proto$2.asMinutes      = asMinutes;
proto$2.asHours        = asHours;
proto$2.asDays         = asDays;
proto$2.asWeeks        = asWeeks;
proto$2.asMonths       = asMonths;
proto$2.asYears        = asYears;
proto$2.valueOf        = valueOf$1;
proto$2._bubble        = bubble;
proto$2.get            = get$2;
proto$2.milliseconds   = milliseconds;
proto$2.seconds        = seconds;
proto$2.minutes        = minutes;
proto$2.hours          = hours;
proto$2.days           = days;
proto$2.weeks          = weeks;
proto$2.months         = months;
proto$2.years          = years;
proto$2.humanize       = humanize;
proto$2.toISOString    = toISOString$1;
proto$2.toString       = toISOString$1;
proto$2.toJSON         = toISOString$1;
proto$2.locale         = locale;
proto$2.localeData     = localeData;

// Deprecations
proto$2.toIsoString = deprecate('toIsoString() is deprecated. Please use toISOString() instead (notice the capitals)', toISOString$1);
proto$2.lang = lang;

// Side effect imports

// FORMATTING

addFormatToken('X', 0, 0, 'unix');
addFormatToken('x', 0, 0, 'valueOf');

// PARSING

addRegexToken('x', matchSigned);
addRegexToken('X', matchTimestamp);
addParseToken('X', function (input, array, config) {
    config._d = new Date(parseFloat(input, 10) * 1000);
});
addParseToken('x', function (input, array, config) {
    config._d = new Date(toInt(input));
});

// Side effect imports


hooks.version = '2.18.1';

setHookCallback(createLocal);

hooks.fn                    = proto;
hooks.min                   = min;
hooks.max                   = max;
hooks.now                   = now;
hooks.utc                   = createUTC;
hooks.unix                  = createUnix;
hooks.months                = listMonths;
hooks.isDate                = isDate;
hooks.locale                = getSetGlobalLocale;
hooks.invalid               = createInvalid;
hooks.duration              = createDuration;
hooks.isMoment              = isMoment;
hooks.weekdays              = listWeekdays;
hooks.parseZone             = createInZone;
hooks.localeData            = getLocale;
hooks.isDuration            = isDuration;
hooks.monthsShort           = listMonthsShort;
hooks.weekdaysMin           = listWeekdaysMin;
hooks.defineLocale          = defineLocale;
hooks.updateLocale          = updateLocale;
hooks.locales               = listLocales;
hooks.weekdaysShort         = listWeekdaysShort;
hooks.normalizeUnits        = normalizeUnits;
hooks.relativeTimeRounding = getSetRelativeTimeRounding;
hooks.relativeTimeThreshold = getSetRelativeTimeThreshold;
hooks.calendarFormat        = getCalendarFormat;
hooks.prototype             = proto;

return hooks;

})));


/*** EXPORTS FROM exports-to-window-loader ***/
window['moment'] = __webpack_require__(42);
/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(304)(module)))

/***/ }),
/* 43 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


exports.__esModule = true;

var _createClass = 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); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

/**
 * CellCoords holds cell coordinates (row, column) and few method to validate them and
 * retrieve as an array or an object
 *
 * @class CellCoords
 */
var CellCoords = function () {
  /**
   * @param {Number} row Row index
   * @param {Number} col Column index
   */
  function CellCoords(row, col) {
    _classCallCheck(this, CellCoords);

    if (typeof row !== 'undefined' && typeof col !== 'undefined') {
      this.row = row;
      this.col = col;
    } else {
      this.row = null;
      this.col = null;
    }
  }

  /**
   * Checks if given set of coordinates is valid in context of a given Walkontable instance
   *
   * @param {Walkontable} wotInstance
   * @returns {Boolean}
   */


  _createClass(CellCoords, [{
    key: 'isValid',
    value: function isValid(wotInstance) {
      // is it a valid cell index (0 or higher)
      if (this.row < 0 || this.col < 0) {
        return false;
      }
      // is selection within total rows and columns
      if (this.row >= wotInstance.getSetting('totalRows') || this.col >= wotInstance.getSetting('totalColumns')) {
        return false;
      }

      return true;
    }

    /**
     * Checks if this cell coords are the same as cell coords given as a parameter
     *
     * @param {CellCoords} cellCoords
     * @returns {Boolean}
     */

  }, {
    key: 'isEqual',
    value: function isEqual(cellCoords) {
      if (cellCoords === this) {
        return true;
      }

      return this.row === cellCoords.row && this.col === cellCoords.col;
    }

    /**
     * Checks if tested coordinates are positioned in south-east from this cell coords
     *
     * @param {Object} testedCoords
     * @returns {Boolean}
     */

  }, {
    key: 'isSouthEastOf',
    value: function isSouthEastOf(testedCoords) {
      return this.row >= testedCoords.row && this.col >= testedCoords.col;
    }

    /**
     * Checks if tested coordinates are positioned in north-east from this cell coords
     *
     * @param {Object} testedCoords
     * @returns {Boolean}
     */

  }, {
    key: 'isNorthWestOf',
    value: function isNorthWestOf(testedCoords) {
      return this.row <= testedCoords.row && this.col <= testedCoords.col;
    }

    /**
     * Checks if tested coordinates are positioned in south-west from this cell coords
     *
     * @param {Object} testedCoords
     * @returns {Boolean}
     */

  }, {
    key: 'isSouthWestOf',
    value: function isSouthWestOf(testedCoords) {
      return this.row >= testedCoords.row && this.col <= testedCoords.col;
    }

    /**
     * Checks if tested coordinates are positioned in north-east from this cell coords
     *
     * @param {Object} testedCoords
     * @returns {Boolean}
     */

  }, {
    key: 'isNorthEastOf',
    value: function isNorthEastOf(testedCoords) {
      return this.row <= testedCoords.row && this.col >= testedCoords.col;
    }
  }]);

  return CellCoords;
}();

exports.default = CellCoords;

/***/ }),
/* 44 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


exports.__esModule = true;

var _element = __webpack_require__(0);

var _autoResize = __webpack_require__(306);

var _autoResize2 = _interopRequireDefault(_autoResize);

var _baseEditor = __webpack_require__(36);

var _baseEditor2 = _interopRequireDefault(_baseEditor);

var _eventManager = __webpack_require__(4);

var _eventManager2 = _interopRequireDefault(_eventManager);

var _unicode = __webpack_require__(15);

var _event = __webpack_require__(7);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

var TextEditor = _baseEditor2.default.prototype.extend();

/**
 * @private
 * @editor TextEditor
 * @class TextEditor
 * @dependencies autoResize
 */
TextEditor.prototype.init = function () {
  var that = this;
  this.createElements();
  this.eventManager = new _eventManager2.default(this);
  this.bindEvents();
  this.autoResize = (0, _autoResize2.default)();

  this.instance.addHook('afterDestroy', function () {
    that.destroy();
  });
};

TextEditor.prototype.getValue = function () {
  return this.TEXTAREA.value;
};

TextEditor.prototype.setValue = function (newValue) {
  this.TEXTAREA.value = newValue;
};

var onBeforeKeyDown = function onBeforeKeyDown(event) {
  var instance = this,
      that = instance.getActiveEditor(),
      ctrlDown;

  // catch CTRL but not right ALT (which in some systems triggers ALT+CTRL)
  ctrlDown = (event.ctrlKey || event.metaKey) && !event.altKey;

  // Process only events that have been fired in the editor
  if (event.target !== that.TEXTAREA || (0, _event.isImmediatePropagationStopped)(event)) {
    return;
  }

  if (event.keyCode === 17 || event.keyCode === 224 || event.keyCode === 91 || event.keyCode === 93) {
    // when CTRL or its equivalent is pressed and cell is edited, don't prepare selectable text in textarea
    (0, _event.stopImmediatePropagation)(event);
    return;
  }

  switch (event.keyCode) {
    case _unicode.KEY_CODES.ARROW_RIGHT:
      if (that.isInFullEditMode()) {
        if (!that.isWaiting() && !that.allowKeyEventPropagation || !that.isWaiting() && that.allowKeyEventPropagation && !that.allowKeyEventPropagation(event.keyCode)) {
          (0, _event.stopImmediatePropagation)(event);
        }
      }
      break;
    case _unicode.KEY_CODES.ARROW_LEFT:
      if (that.isInFullEditMode()) {
        if (!that.isWaiting() && !that.allowKeyEventPropagation || !that.isWaiting() && that.allowKeyEventPropagation && !that.allowKeyEventPropagation(event.keyCode)) {
          (0, _event.stopImmediatePropagation)(event);
        }
      }
      break;
    case _unicode.KEY_CODES.ARROW_UP:
    case _unicode.KEY_CODES.ARROW_DOWN:
      if (that.isInFullEditMode()) {
        if (!that.isWaiting() && !that.allowKeyEventPropagation || !that.isWaiting() && that.allowKeyEventPropagation && !that.allowKeyEventPropagation(event.keyCode)) {
          (0, _event.stopImmediatePropagation)(event);
        }
      }
      break;

    case _unicode.KEY_CODES.ENTER:
      var selected = that.instance.getSelected();
      var isMultipleSelection = !(selected[0] === selected[2] && selected[1] === selected[3]);
      if (ctrlDown && !isMultipleSelection || event.altKey) {
        // if ctrl+enter or alt+enter, add new line
        if (that.isOpened()) {
          var caretPosition = (0, _element.getCaretPosition)(that.TEXTAREA),
              value = that.getValue();

          var newValue = value.slice(0, caretPosition) + '\n' + value.slice(caretPosition);

          that.setValue(newValue);

          (0, _element.setCaretPosition)(that.TEXTAREA, caretPosition + 1);
        } else {
          that.beginEditing(that.originalValue + '\n');
        }
        (0, _event.stopImmediatePropagation)(event);
      }
      event.preventDefault(); // don't add newline to field
      break;

    case _unicode.KEY_CODES.A:
    case _unicode.KEY_CODES.X:
    case _unicode.KEY_CODES.C:
    case _unicode.KEY_CODES.V:
      if (ctrlDown) {
        (0, _event.stopImmediatePropagation)(event); // CTRL+A, CTRL+C, CTRL+V, CTRL+X should only work locally when cell is edited (not in table context)
      }
      break;

    case _unicode.KEY_CODES.BACKSPACE:
    case _unicode.KEY_CODES.DELETE:
    case _unicode.KEY_CODES.HOME:
    case _unicode.KEY_CODES.END:
      (0, _event.stopImmediatePropagation)(event); // backspace, delete, home, end should only work locally when cell is edited (not in table context)
      break;
    default:
      break;
  }

  if ([_unicode.KEY_CODES.ARROW_UP, _unicode.KEY_CODES.ARROW_RIGHT, _unicode.KEY_CODES.ARROW_DOWN, _unicode.KEY_CODES.ARROW_LEFT].indexOf(event.keyCode) === -1) {
    that.autoResize.resize(String.fromCharCode(event.keyCode));
  }
};

TextEditor.prototype.open = function () {
  this.refreshDimensions(); // need it instantly, to prevent https://github.com/handsontable/handsontable/issues/348

  this.instance.addHook('beforeKeyDown', onBeforeKeyDown);
};

TextEditor.prototype.close = function (tdOutside) {
  this.textareaParentStyle.display = 'none';

  this.autoResize.unObserve();

  if (document.activeElement === this.TEXTAREA) {
    this.instance.listen(); // don't refocus the table if user focused some cell outside of HT on purpose
  }
  this.instance.removeHook('beforeKeyDown', onBeforeKeyDown);
};

TextEditor.prototype.focus = function () {
  this.TEXTAREA.focus();
  (0, _element.setCaretPosition)(this.TEXTAREA, this.TEXTAREA.value.length);
};

TextEditor.prototype.createElements = function () {
  //    this.$body = $(document.body);

  this.TEXTAREA = document.createElement('TEXTAREA');

  (0, _element.addClass)(this.TEXTAREA, 'handsontableInput');

  this.textareaStyle = this.TEXTAREA.style;
  this.textareaStyle.width = 0;
  this.textareaStyle.height = 0;

  this.TEXTAREA_PARENT = document.createElement('DIV');
  (0, _element.addClass)(this.TEXTAREA_PARENT, 'handsontableInputHolder');

  this.textareaParentStyle = this.TEXTAREA_PARENT.style;
  this.textareaParentStyle.top = 0;
  this.textareaParentStyle.left = 0;
  this.textareaParentStyle.display = 'none';

  this.TEXTAREA_PARENT.appendChild(this.TEXTAREA);

  this.instance.rootElement.appendChild(this.TEXTAREA_PARENT);

  var that = this;
  this.instance._registerTimeout(setTimeout(function () {
    that.refreshDimensions();
  }, 0));
};

TextEditor.prototype.getEditedCell = function () {
  var editorSection = this.checkEditorSection(),
      editedCell;

  switch (editorSection) {
    case 'top':
      editedCell = this.instance.view.wt.wtOverlays.topOverlay.clone.wtTable.getCell({
        row: this.row,
        col: this.col
      });
      this.textareaParentStyle.zIndex = 101;
      break;
    case 'top-left-corner':
      editedCell = this.instance.view.wt.wtOverlays.topLeftCornerOverlay.clone.wtTable.getCell({
        row: this.row,
        col: this.col
      });
      this.textareaParentStyle.zIndex = 103;
      break;
    case 'bottom-left-corner':
      editedCell = this.instance.view.wt.wtOverlays.bottomLeftCornerOverlay.clone.wtTable.getCell({
        row: this.row,
        col: this.col
      });
      this.textareaParentStyle.zIndex = 103;
      break;
    case 'left':
      editedCell = this.instance.view.wt.wtOverlays.leftOverlay.clone.wtTable.getCell({
        row: this.row,
        col: this.col
      });
      this.textareaParentStyle.zIndex = 102;
      break;
    case 'bottom':
      editedCell = this.instance.view.wt.wtOverlays.bottomOverlay.clone.wtTable.getCell({
        row: this.row,
        col: this.col
      });
      this.textareaParentStyle.zIndex = 102;
      break;
    default:
      editedCell = this.instance.getCell(this.row, this.col);
      this.textareaParentStyle.zIndex = '';
      break;
  }

  return editedCell != -1 && editedCell != -2 ? editedCell : void 0;
};

TextEditor.prototype.refreshValue = function () {
  var sourceData = this.instance.getSourceDataAtCell(this.row, this.prop);
  this.originalValue = sourceData;

  this.setValue(sourceData);
  this.refreshDimensions();
};

TextEditor.prototype.refreshDimensions = function () {
  if (this.state !== _baseEditor.EditorState.EDITING) {
    return;
  }
  this.TD = this.getEditedCell();

  // TD is outside of the viewport.
  if (!this.TD) {
    this.close(true);

    return;
  }
  var currentOffset = (0, _element.offset)(this.TD),
      containerOffset = (0, _element.offset)(this.instance.rootElement),
      scrollableContainer = (0, _element.getScrollableElement)(this.TD),
      totalRowsCount = this.instance.countRows(),


  // If colHeaders is disabled, cells in the first row have border-top
  editTopModifier = currentOffset.top === containerOffset.top ? 0 : 1,
      editTop = currentOffset.top - containerOffset.top - editTopModifier - (scrollableContainer.scrollTop || 0),
      editLeft = currentOffset.left - containerOffset.left - 1 - (scrollableContainer.scrollLeft || 0),
      settings = this.instance.getSettings(),
      rowHeadersCount = this.instance.hasRowHeaders(),
      colHeadersCount = this.instance.hasColHeaders(),
      editorSection = this.checkEditorSection(),
      backgroundColor = this.TD.style.backgroundColor,
      cssTransformOffset;

  // TODO: Refactor this to the new instance.getCell method (from #ply-59), after 0.12.1 is released
  switch (editorSection) {
    case 'top':
      cssTransformOffset = (0, _element.getCssTransform)(this.instance.view.wt.wtOverlays.topOverlay.clone.wtTable.holder.parentNode);
      break;
    case 'left':
      cssTransformOffset = (0, _element.getCssTransform)(this.instance.view.wt.wtOverlays.leftOverlay.clone.wtTable.holder.parentNode);
      break;
    case 'top-left-corner':
      cssTransformOffset = (0, _element.getCssTransform)(this.instance.view.wt.wtOverlays.topLeftCornerOverlay.clone.wtTable.holder.parentNode);
      break;
    case 'bottom-left-corner':
      cssTransformOffset = (0, _element.getCssTransform)(this.instance.view.wt.wtOverlays.bottomLeftCornerOverlay.clone.wtTable.holder.parentNode);
      break;
    case 'bottom':
      cssTransformOffset = (0, _element.getCssTransform)(this.instance.view.wt.wtOverlays.bottomOverlay.clone.wtTable.holder.parentNode);
      break;
    default:
      break;
  }

  if (colHeadersCount && this.instance.getSelected()[0] === 0 || settings.fixedRowsBottom && this.instance.getSelected()[0] === totalRowsCount - settings.fixedRowsBottom) {
    editTop += 1;
  }

  if (this.instance.getSelected()[1] === 0) {
    editLeft += 1;
  }

  if (cssTransformOffset && cssTransformOffset != -1) {
    this.textareaParentStyle[cssTransformOffset[0]] = cssTransformOffset[1];
  } else {
    (0, _element.resetCssTransform)(this.TEXTAREA_PARENT);
  }

  this.textareaParentStyle.top = editTop + 'px';
  this.textareaParentStyle.left = editLeft + 'px';

  var firstRowOffset = this.instance.view.wt.wtViewport.rowsRenderCalculator.startPosition;
  var firstColumnOffset = this.instance.view.wt.wtViewport.columnsRenderCalculator.startPosition;
  var horizontalScrollPosition = this.instance.view.wt.wtOverlays.leftOverlay.getScrollPosition();
  var verticalScrollPosition = this.instance.view.wt.wtOverlays.topOverlay.getScrollPosition();
  var scrollbarWidth = (0, _element.getScrollbarWidth)();

  var cellTopOffset = this.TD.offsetTop + firstRowOffset - verticalScrollPosition;
  var cellLeftOffset = this.TD.offsetLeft + firstColumnOffset - horizontalScrollPosition;

  var width = (0, _element.innerWidth)(this.TD) - 8;
  var actualVerticalScrollbarWidth = (0, _element.hasVerticalScrollbar)(scrollableContainer) ? scrollbarWidth : 0;
  var actualHorizontalScrollbarWidth = (0, _element.hasHorizontalScrollbar)(scrollableContainer) ? scrollbarWidth : 0;
  var maxWidth = this.instance.view.maximumVisibleElementWidth(cellLeftOffset) - 9 - actualVerticalScrollbarWidth;
  var height = this.TD.scrollHeight + 1;
  var maxHeight = Math.max(this.instance.view.maximumVisibleElementHeight(cellTopOffset) - actualHorizontalScrollbarWidth, 23);

  var cellComputedStyle = (0, _element.getComputedStyle)(this.TD);

  this.TEXTAREA.style.fontSize = cellComputedStyle.fontSize;
  this.TEXTAREA.style.fontFamily = cellComputedStyle.fontFamily;
  this.TEXTAREA.style.backgroundColor = ''; // RESET STYLE
  this.TEXTAREA.style.backgroundColor = backgroundColor ? backgroundColor : (0, _element.getComputedStyle)(this.TEXTAREA).backgroundColor;

  this.autoResize.init(this.TEXTAREA, {
    minHeight: Math.min(height, maxHeight),
    maxHeight: maxHeight, // TEXTAREA should never be wider than visible part of the viewport (should not cover the scrollbar)
    minWidth: Math.min(width, maxWidth),
    maxWidth: maxWidth // TEXTAREA should never be wider than visible part of the viewport (should not cover the scrollbar)
  }, true);

  this.textareaParentStyle.display = 'block';
};

TextEditor.prototype.bindEvents = function () {
  var editor = this;

  this.eventManager.addEventListener(this.TEXTAREA, 'cut', function (event) {
    (0, _event.stopPropagation)(event);
  });

  this.eventManager.addEventListener(this.TEXTAREA, 'paste', function (event) {
    (0, _event.stopPropagation)(event);
  });

  this.instance.addHook('afterScrollHorizontally', function () {
    editor.refreshDimensions();
  });

  this.instance.addHook('afterScrollVertically', function () {
    editor.refreshDimensions();
  });

  this.instance.addHook('afterColumnResize', function () {
    editor.refreshDimensions();
    editor.focus();
  });

  this.instance.addHook('afterRowResize', function () {
    editor.refreshDimensions();
    editor.focus();
  });

  this.instance.addHook('afterDestroy', function () {
    editor.eventManager.destroy();
  });
};

TextEditor.prototype.destroy = function () {
  this.eventManager.destroy();
};

exports.default = TextEditor;

/***/ }),
/* 45 */
/***/ (function(module, exports) {

var core = module.exports = { version: '2.5.1' };
if (typeof __e == 'number') __e = core; // eslint-disable-line no-undef


/***/ }),
/* 46 */
/***/ (function(module, exports) {

module.exports = {};


/***/ }),
/* 47 */
/***/ (function(module, exports, __webpack_require__) {

var META = __webpack_require__(51)('meta');
var isObject = __webpack_require__(12);
var has = __webpack_require__(26);
var setDesc = __webpack_require__(18).f;
var id = 0;
var isExtensible = Object.isExtensible || function () {
  return true;
};
var FREEZE = !__webpack_require__(25)(function () {
  return isExtensible(Object.preventExtensions({}));
});
var setMeta = function (it) {
  setDesc(it, META, { value: {
    i: 'O' + ++id, // object ID
    w: {}          // weak collections IDs
  } });
};
var fastKey = function (it, create) {
  // return primitive with prefix
  if (!isObject(it)) return typeof it == 'symbol' ? it : (typeof it == 'string' ? 'S' : 'P') + it;
  if (!has(it, META)) {
    // can't set metadata to uncaught frozen object
    if (!isExtensible(it)) return 'F';
    // not necessary to add metadata
    if (!create) return 'E';
    // add missing metadata
    setMeta(it);
  // return object ID
  } return it[META].i;
};
var getWeak = function (it, create) {
  if (!has(it, META)) {
    // can't set metadata to uncaught frozen object
    if (!isExtensible(it)) return true;
    // not necessary to add metadata
    if (!create) return false;
    // add missing metadata
    setMeta(it);
  // return hash weak collections IDs
  } return it[META].w;
};
// add metadata on freeze-family methods calling
var onFreeze = function (it) {
  if (FREEZE && meta.NEED && isExtensible(it) && !has(it, META)) setMeta(it);
  return it;
};
var meta = module.exports = {
  KEY: META,
  NEED: false,
  fastKey: fastKey,
  getWeak: getWeak,
  onFreeze: onFreeze
};


/***/ }),
/* 48 */
/***/ (function(module, exports) {

exports.f = {}.propertyIsEnumerable;


/***/ }),
/* 49 */
/***/ (function(module, exports) {

module.exports = function (bitmap, value) {
  return {
    enumerable: !(bitmap & 1),
    configurable: !(bitmap & 2),
    writable: !(bitmap & 4),
    value: value
  };
};


/***/ }),
/* 50 */
/***/ (function(module, exports, __webpack_require__) {

var def = __webpack_require__(18).f;
var has = __webpack_require__(26);
var TAG = __webpack_require__(8)('toStringTag');

module.exports = function (it, tag, stat) {
  if (it && !has(it = stat ? it : it.prototype, TAG)) def(it, TAG, { configurable: true, value: tag });
};


/***/ }),
/* 51 */
/***/ (function(module, exports) {

var id = 0;
var px = Math.random();
module.exports = function (key) {
  return 'Symbol('.concat(key === undefined ? '' : key, ')_', (++id + px).toString(36));
};


/***/ }),
/* 52 */
/***/ (function(module, exports, __webpack_require__) {

var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/*!
 * numbro.js
 * version : 1.11.0
 * author : Företagsplatsen AB
 * license : MIT
 * http://www.foretagsplatsen.se
 */

(function () {
    'use strict';

    /************************************
        Constants
    ************************************/

    var numbro,
        VERSION = '1.11.0',
        binarySuffixes = ['B', 'KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB'],
        decimalSuffixes = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'],
        bytes = {
            general: { scale: 1024, suffixes: decimalSuffixes, marker: 'bd' },
            binary:  { scale: 1024, suffixes: binarySuffixes, marker: 'b' },
            decimal: { scale: 1000, suffixes: decimalSuffixes, marker: 'd' }
        },
        // general must be before the others because it reuses their characters!
        byteFormatOrder = [ bytes.general, bytes.binary, bytes.decimal ],
    // internal storage for culture config files
        cultures = {},
    // Todo: Remove in 2.0.0
        languages = cultures,
        currentCulture = 'en-US',
        zeroFormat = null,
        defaultFormat = '0,0',
        defaultCurrencyFormat = '0$',
        // check for nodeJS
        hasModule = (typeof module !== 'undefined' && module.exports),
    // default culture
        enUS = {
            delimiters: {
                thousands: ',',
                decimal: '.'
            },
            abbreviations: {
                thousand: 'k',
                million: 'm',
                billion: 'b',
                trillion: 't'
            },
            ordinal: function(number) {
                var b = number % 10;
                return (~~(number % 100 / 10) === 1) ? 'th' :
                    (b === 1) ? 'st' :
                        (b === 2) ? 'nd' :
                            (b === 3) ? 'rd' : 'th';
            },
            currency: {
                symbol: '$',
                position: 'prefix'
            },
            defaults: {
                currencyFormat: ',0000 a'
            },
            formats: {
                fourDigits: '0000 a',
                fullWithTwoDecimals: '$ ,0.00',
                fullWithTwoDecimalsNoCurrency: ',0.00'
            }
        };

    /************************************
        Constructors
    ************************************/


    // Numbro prototype object
    function Numbro(number) {
        this._value = number;
    }

    function numberLength(number) {
        if (number === 0) { return 1; }
        return Math.floor(Math.log(Math.abs(number)) / Math.LN10) + 1;
    }

    function zeroes(count) {
        var i, ret = '';

        for (i = 0; i < count; i++) {
            ret += '0';
        }

        return ret;
    }
    /**
     * Implementation of toFixed() for numbers with exponents
     * This function may return negative representations for zero values e.g. "-0.0"
     */
    function toFixedLargeSmall(value, precision) {
        var mantissa,
            beforeDec,
            afterDec,
            exponent,
            prefix,
            endStr,
            zerosStr,
            str;

        str = value.toString();

        mantissa = str.split('e')[0];
        exponent = str.split('e')[1];

        beforeDec = mantissa.split('.')[0];
        afterDec = mantissa.split('.')[1] || '';

        if (+exponent > 0) {
            // exponent is positive - add zeros after the numbers
            str = beforeDec + afterDec + zeroes(exponent - afterDec.length);
        } else {
            // exponent is negative

            if (+beforeDec < 0) {
                prefix = '-0';
            } else {
                prefix = '0';
            }

            // tack on the decimal point if needed
            if (precision > 0) {
                prefix += '.';
            }

            zerosStr = zeroes((-1 * exponent) - 1);
            // substring off the end to satisfy the precision
            endStr = (zerosStr + Math.abs(beforeDec) + afterDec).substr(0, precision);
            str = prefix + endStr;
        }

        // only add percision 0's if the exponent is positive
        if (+exponent > 0 && precision > 0) {
            str += '.' + zeroes(precision);
        }

        return str;
    }

    /**
     * Implementation of toFixed() that treats floats more like decimals
     *
     * Fixes binary rounding issues (eg. (0.615).toFixed(2) === '0.61') that present
     * problems for accounting- and finance-related software.
     *
     * Also removes negative signs for zero-formatted numbers. e.g. -0.01 w/ precision 1 -> 0.0
     */
    function toFixed(value, precision, roundingFunction, optionals) {
        var power = Math.pow(10, precision),
            optionalsRegExp,
            output;

        if (value.toString().indexOf('e') > -1) {
            // toFixed returns scientific notation for numbers above 1e21 and below 1e-7
            output = toFixedLargeSmall(value, precision);
            // remove the leading negative sign if it exists and should not be present (e.g. -0.00)
            if (output.charAt(0) === '-' && +output >= 0) {
                output = output.substr(1); // chop off the '-'
            }
        }
        else {
            // Multiply up by precision, round accurately, then divide and use native toFixed():
            output = (roundingFunction(value + 'e+' + precision) / power).toFixed(precision);
        }

        if (optionals) {
            optionalsRegExp = new RegExp('0{1,' + optionals + '}$');
            output = output.replace(optionalsRegExp, '');
        }

        return output;
    }

    /************************************
        Formatting
    ************************************/

    // determine what type of formatting we need to do
    function formatNumbro(n, format, roundingFunction) {
        var output,
            escapedFormat = format.replace(/\{[^\{\}]*\}/g, '');

        // figure out what kind of format we are dealing with
        if (escapedFormat.indexOf('$') > -1) { // currency!!!!!
            output = formatCurrency(n, cultures[currentCulture].currency.symbol, format, roundingFunction);
        } else if (escapedFormat.indexOf('%') > -1) { // percentage
            output = formatPercentage(n, format, roundingFunction);
        } else if (escapedFormat.indexOf(':') > -1) { // time
            output = formatTime(n, format);
        } else { // plain ol' numbers or bytes
            output = formatNumber(n._value, format, roundingFunction);
        }

        // return string
        return output;
    }

    // revert to number
    function unformatNumbro(n, string) {
        var stringOriginal = string,
            thousandRegExp,
            millionRegExp,
            billionRegExp,
            trillionRegExp,
            bytesMultiplier = false,
            power;

        if (string.indexOf(':') > -1) {
            n._value = unformatTime(string);
        } else {
            if (string === zeroFormat) {
                n._value = 0;
            } else {
                if (cultures[currentCulture].delimiters.decimal !== '.') {
                    string = string.replace(/\./g, '').replace(cultures[currentCulture].delimiters.decimal, '.');
                }

                // see if abbreviations are there so that we can multiply to the correct number
                thousandRegExp = new RegExp('[^a-zA-Z]' + cultures[currentCulture].abbreviations.thousand +
                    '(?:\\)|(\\' + cultures[currentCulture].currency.symbol + ')?(?:\\))?)?$');
                millionRegExp = new RegExp('[^a-zA-Z]' + cultures[currentCulture].abbreviations.million +
                    '(?:\\)|(\\' + cultures[currentCulture].currency.symbol + ')?(?:\\))?)?$');
                billionRegExp = new RegExp('[^a-zA-Z]' + cultures[currentCulture].abbreviations.billion +
                    '(?:\\)|(\\' + cultures[currentCulture].currency.symbol + ')?(?:\\))?)?$');
                trillionRegExp = new RegExp('[^a-zA-Z]' + cultures[currentCulture].abbreviations.trillion +
                    '(?:\\)|(\\' + cultures[currentCulture].currency.symbol + ')?(?:\\))?)?$');

                // see if bytes are there so that we can multiply to the correct number
                for (power = 1; power < binarySuffixes.length && !bytesMultiplier; ++power) {
                    if (string.indexOf(binarySuffixes[power]) > -1) {
                        bytesMultiplier = Math.pow(1024, power);
                    } else if (string.indexOf(decimalSuffixes[power]) > -1) {
                        bytesMultiplier = Math.pow(1000, power);
                    }
                }

                var str = string.replace(/[^0-9\.]+/g, '');
                if (str === '') {
                    // An empty string is not a number.
                    n._value = NaN;

                } else {
                    // do some math to create our number
                    n._value = ((bytesMultiplier) ? bytesMultiplier : 1) *
                        ((stringOriginal.match(thousandRegExp)) ? Math.pow(10, 3) : 1) *
                        ((stringOriginal.match(millionRegExp)) ? Math.pow(10, 6) : 1) *
                        ((stringOriginal.match(billionRegExp)) ? Math.pow(10, 9) : 1) *
                        ((stringOriginal.match(trillionRegExp)) ? Math.pow(10, 12) : 1) *
                        ((string.indexOf('%') > -1) ? 0.01 : 1) *
                        (((string.split('-').length +
                            Math.min(string.split('(').length - 1, string.split(')').length - 1)) % 2) ? 1 : -1) *
                        Number(str);

                    // round if we are talking about bytes
                    n._value = (bytesMultiplier) ? Math.ceil(n._value) : n._value;
                }
            }
        }
        return n._value;
    }

    function formatCurrency(n, currencySymbol, originalFormat, roundingFunction) {
        var format = originalFormat,
            symbolIndex = format.indexOf('$'),
            openParenIndex = format.indexOf('('),
            plusSignIndex = format.indexOf('+'),
            minusSignIndex = format.indexOf('-'),
            space = '',
            decimalSeparator = '',
            spliceIndex,
            output;

        if(format.indexOf('$') === -1){
            // Use defaults instead of the format provided
            if (cultures[currentCulture].currency.position === 'infix') {
                decimalSeparator = currencySymbol;
                if (cultures[currentCulture].currency.spaceSeparated) {
                    decimalSeparator = ' ' + decimalSeparator + ' ';
                }
            } else if (cultures[currentCulture].currency.spaceSeparated) {
                space = ' ';
            }
        } else {
            // check for space before or after currency
            if (format.indexOf(' $') > -1) {
                space = ' ';
                format = format.replace(' $', '');
            } else if (format.indexOf('$ ') > -1) {
                space = ' ';
                format = format.replace('$ ', '');
            } else {
                format = format.replace('$', '');
            }
        }

        // Format The Number
        output = formatNumber(n._value, format, roundingFunction, decimalSeparator);

        if (originalFormat.indexOf('$') === -1) {
            // Use defaults instead of the format provided
            switch (cultures[currentCulture].currency.position) {
                case 'postfix':
                    if (output.indexOf(')') > -1) {
                        output = output.split('');
                        output.splice(-1, 0, space + currencySymbol);
                        output = output.join('');
                    } else {
                        output = output + space + currencySymbol;
                    }
                    break;
                case 'infix':
                    break;
                case 'prefix':
                    if (output.indexOf('(') > -1 || output.indexOf('-') > -1) {
                        output = output.split('');
                        spliceIndex = Math.max(openParenIndex, minusSignIndex) + 1;

                        output.splice(spliceIndex, 0, currencySymbol + space);
                        output = output.join('');
                    } else {
                        output = currencySymbol + space + output;
                    }
                    break;
                default:
                    throw Error('Currency position should be among ["prefix", "infix", "postfix"]');
            }
        } else {
            // position the symbol
            if (symbolIndex <= 1) {
                if (output.indexOf('(') > -1 || output.indexOf('+') > -1 || output.indexOf('-') > -1) {
                    output = output.split('');
                    spliceIndex = 1;
                    if (symbolIndex < openParenIndex || symbolIndex < plusSignIndex || symbolIndex < minusSignIndex) {
                        // the symbol appears before the "(", "+" or "-"
                        spliceIndex = 0;
                    }
                    output.splice(spliceIndex, 0, currencySymbol + space);
                    output = output.join('');
                } else {
                    output = currencySymbol + space + output;
                }
            } else {
                if (output.indexOf(')') > -1) {
                    output = output.split('');
                    output.splice(-1, 0, space + currencySymbol);
                    output = output.join('');
                } else {
                    output = output + space + currencySymbol;
                }
            }
        }

        return output;
    }

    function formatForeignCurrency(n, foreignCurrencySymbol, originalFormat, roundingFunction) {
        return formatCurrency(n, foreignCurrencySymbol, originalFormat, roundingFunction);
    }

    function formatPercentage(n, format, roundingFunction) {
        var space = '',
            output,
            value = n._value * 100;

        // check for space before %
        if (format.indexOf(' %') > -1) {
            space = ' ';
            format = format.replace(' %', '');
        } else {
            format = format.replace('%', '');
        }

        output = formatNumber(value, format, roundingFunction);

        if (output.indexOf(')') > -1) {
            output = output.split('');
            output.splice(-1, 0, space + '%');
            output = output.join('');
        } else {
            output = output + space + '%';
        }

        return output;
    }

    function formatTime(n) {
        var hours = Math.floor(n._value / 60 / 60),
            minutes = Math.floor((n._value - (hours * 60 * 60)) / 60),
            seconds = Math.round(n._value - (hours * 60 * 60) - (minutes * 60));
        return hours + ':' +
            ((minutes < 10) ? '0' + minutes : minutes) + ':' +
            ((seconds < 10) ? '0' + seconds : seconds);
    }

    function unformatTime(string) {
        var timeArray = string.split(':'),
            seconds = 0;
        // turn hours and minutes into seconds and add them all up
        if (timeArray.length === 3) {
            // hours
            seconds = seconds + (Number(timeArray[0]) * 60 * 60);
            // minutes
            seconds = seconds + (Number(timeArray[1]) * 60);
            // seconds
            seconds = seconds + Number(timeArray[2]);
        } else if (timeArray.length === 2) {
            // minutes
            seconds = seconds + (Number(timeArray[0]) * 60);
            // seconds
            seconds = seconds + Number(timeArray[1]);
        }
        return Number(seconds);
    }

    function formatByteUnits (value, suffixes, scale) {
        var suffix = suffixes[0],
            power,
            min,
            max,
            abs = Math.abs(value);

        if (abs >= scale) {
            for (power = 1; power < suffixes.length; ++power) {
                min = Math.pow(scale, power);
                max = Math.pow(scale, power + 1);

                if (abs >= min && abs < max) {
                    suffix = suffixes[power];
                    value = value / min;
                    break;
                }
            }

            // values greater than or equal to [scale] YB never set the suffix
            if (suffix === suffixes[0]) {
                value = value / Math.pow(scale, suffixes.length - 1);
                suffix = suffixes[suffixes.length - 1];
            }
        }

        return { value: value, suffix: suffix };
    }

    function formatNumber (value, format, roundingFunction, sep) {
        var negP = false,
            signed = false,
            optDec = false,
            abbr = '',
            abbrK = false, // force abbreviation to thousands
            abbrM = false, // force abbreviation to millions
            abbrB = false, // force abbreviation to billions
            abbrT = false, // force abbreviation to trillions
            abbrForce = false, // force abbreviation
            bytes = '',
            byteFormat,
            units,
            ord = '',
            abs = Math.abs(value),
            totalLength,
            length,
            minimumPrecision,
            pow,
            w,
            intPrecision,
            precision,
            prefix,
            postfix,
            thousands,
            d = '',
            forcedNeg = false,
            neg = false,
            indexOpenP,
            indexMinus,
            paren = '',
            minlen,
            i;

        // check if number is zero and a custom zero format has been set
        if (value === 0 && zeroFormat !== null) {
            return zeroFormat;
        }

        if (!isFinite(value)) {
            return '' + value;
        }

        if (format.indexOf('{') === 0) {
            var end = format.indexOf('}');
            if (end === -1) {
                throw Error('Format should also contain a "}"');
            }
            prefix = format.slice(1, end);
            format = format.slice(end + 1);
        } else {
            prefix = '';
        }

        if (format.indexOf('}') === format.length - 1 && format.length) {
            var start = format.indexOf('{');
            if (start === -1) {
                throw Error('Format should also contain a "{"');
            }
            postfix = format.slice(start + 1, -1);
            format = format.slice(0, start + 1);
        } else {
            postfix = '';
        }

        // check for min length
        var info;
        if (format.indexOf('.') === -1) {
            info = format.match(/([0-9]+).*/);
        } else {
            info = format.match(/([0-9]+)\..*/);
        }
        minlen = info === null ? -1 : info[1].length;

        // see if we should use parentheses for negative number or if we should prefix with a sign
        // if both are present we default to parentheses
        if (format.indexOf('-') !== -1) {
            forcedNeg = true;
        }
        if (format.indexOf('(') > -1) {
            negP = true;
            format = format.slice(1, -1);
        } else if (format.indexOf('+') > -1) {
            signed = true;
            format = format.replace(/\+/g, '');
        }

        // see if abbreviation is wanted
        if (format.indexOf('a') > -1) {
            intPrecision = format.split('.')[0].match(/[0-9]+/g) || ['0'];
            intPrecision = parseInt(intPrecision[0], 10);

            // check if abbreviation is specified
            abbrK = format.indexOf('aK') >= 0;
            abbrM = format.indexOf('aM') >= 0;
            abbrB = format.indexOf('aB') >= 0;
            abbrT = format.indexOf('aT') >= 0;
            abbrForce = abbrK || abbrM || abbrB || abbrT;

            // check for space before abbreviation
            if (format.indexOf(' a') > -1) {
                abbr = ' ';
                format = format.replace(' a', '');
            } else {
                format = format.replace('a', '');
            }

            totalLength = numberLength(value);
            minimumPrecision = totalLength % 3;
            minimumPrecision = minimumPrecision === 0 ? 3 : minimumPrecision;

            if (intPrecision && abs !== 0) {
                pow = 3 * ~~((Math.min(intPrecision, totalLength) - minimumPrecision) / 3);
                abs = abs / Math.pow(10, pow);
            }

            if (totalLength !== intPrecision) {
                if (abs >= Math.pow(10, 12) && !abbrForce || abbrT) {
                    // trillion
                    abbr = abbr + cultures[currentCulture].abbreviations.trillion;
                    value = value / Math.pow(10, 12);
                } else if (abs < Math.pow(10, 12) && abs >= Math.pow(10, 9) && !abbrForce || abbrB) {
                    // billion
                    abbr = abbr + cultures[currentCulture].abbreviations.billion;
                    value = value / Math.pow(10, 9);
                } else if (abs < Math.pow(10, 9) && abs >= Math.pow(10, 6) && !abbrForce || abbrM) {
                    // million
                    abbr = abbr + cultures[currentCulture].abbreviations.million;
                    value = value / Math.pow(10, 6);
                } else if (abs < Math.pow(10, 6) && abs >= Math.pow(10, 3) && !abbrForce || abbrK) {
                    // thousand
                    abbr = abbr + cultures[currentCulture].abbreviations.thousand;
                    value = value / Math.pow(10, 3);
                }
            }

            length = numberLength(value);
            if (intPrecision && length < intPrecision && format.indexOf('.') === -1) {
                format += '[.]';
                format += zeroes(intPrecision - length);
            }
        }

        // see if we are formatting
        //   binary-decimal bytes (1024 MB), binary bytes (1024 MiB), or decimal bytes (1000 MB)
        for (i = 0; i < byteFormatOrder.length; ++i) {
            byteFormat = byteFormatOrder[i];

            if (format.indexOf(byteFormat.marker) > -1) {
                // check for space before
                if (format.indexOf(' ' + byteFormat.marker) >-1) {
                    bytes = ' ';
                }

                // remove the marker (with the space if it had one)
                format = format.replace(bytes + byteFormat.marker, '');

                units = formatByteUnits(value, byteFormat.suffixes, byteFormat.scale);

                value = units.value;
                bytes = bytes + units.suffix;

                break;
            }
        }

        // see if ordinal is wanted
        if (format.indexOf('o') > -1) {
            // check for space before
            if (format.indexOf(' o') > -1) {
                ord = ' ';
                format = format.replace(' o', '');
            } else {
                format = format.replace('o', '');
            }

            if (cultures[currentCulture].ordinal) {
                ord = ord + cultures[currentCulture].ordinal(value);
            }
        }

        if (format.indexOf('[.]') > -1) {
            optDec = true;
            format = format.replace('[.]', '.');
        }

        precision = format.split('.')[1];
        thousands = format.indexOf(',');

        if (precision) {
            var dSplit = [];

            if (precision.indexOf('*') !== -1) {
                d = value.toString();
                dSplit = d.split('.');
                if (dSplit.length > 1) {
                    d = toFixed(value, dSplit[1].length, roundingFunction);
                }
            } else {
                if (precision.indexOf('[') > -1) {
                    precision = precision.replace(']', '');
                    precision = precision.split('[');
                    d = toFixed(value, (precision[0].length + precision[1].length), roundingFunction,
                        precision[1].length);
                } else {
                    d = toFixed(value, precision.length, roundingFunction);
                }
            }

            dSplit = d.split('.');
            w = dSplit[0];

            if (dSplit.length > 1 && dSplit[1].length) {
                var p = sep ? abbr + sep : cultures[currentCulture].delimiters.decimal;
                d = p + dSplit[1];
            } else {
                d = '';
            }

            if (optDec && Number(d.slice(1)) === 0) {
                d = '';
            }
        } else {
            w = toFixed(value, 0, roundingFunction);
        }

        // format number
        if (w.indexOf('-') > -1) {
            w = w.slice(1);
            neg = true;
        }

        if (w.length < minlen) {
            w = zeroes(minlen - w.length) + w;
        }

        if (thousands > -1) {
            w = w.toString().replace(/(\d)(?=(\d{3})+(?!\d))/g, '$1' +
                cultures[currentCulture].delimiters.thousands);
        }

        if (format.indexOf('.') === 0) {
            w = '';
        }

        indexOpenP = format.indexOf('(');
        indexMinus = format.indexOf('-');

        if (indexOpenP < indexMinus) {
            paren = ((negP && neg) ? '(' : '') + (((forcedNeg && neg) || (!negP && neg)) ? '-' : '');
        } else {
            paren = (((forcedNeg && neg) || (!negP && neg)) ? '-' : '') + ((negP && neg) ? '(' : '');
        }

        return prefix +
            paren + ((!neg && signed && value !== 0) ? '+' : '') +
            w + d +
            ((ord) ? ord : '') +
            ((abbr && !sep) ? abbr : '') +
            ((bytes) ? bytes : '') +
            ((negP && neg) ? ')' : '') +
            postfix;
    }

    /************************************
        Top Level Functions
    ************************************/

    numbro = function(input) {
        if (numbro.isNumbro(input)) {
            input = input.value();
        } else if (typeof input === 'string' || typeof input === 'number') {
            input = numbro.fn.unformat(input);
        } else {
            input = NaN;
        }

        return new Numbro(Number(input));
    };

    // version number
    numbro.version = VERSION;

    // compare numbro object
    numbro.isNumbro = function(obj) {
        return obj instanceof Numbro;
    };

    /**
     * This function allow the user to set a new language with a fallback if
     * the language does not exist. If no fallback language is provided,
     * it fallbacks to english.
     *
     * @deprecated Since in version 1.6.0. It will be deleted in version 2.0
     * `setCulture` should be used instead.
     */
    numbro.setLanguage = function(newLanguage, fallbackLanguage) {
        console.warn('`setLanguage` is deprecated since version 1.6.0. Use `setCulture` instead');
        var key = newLanguage,
            prefix = newLanguage.split('-')[0],
            matchingLanguage = null;
        if (!languages[key]) {
            Object.keys(languages).forEach(function(language) {
                if (!matchingLanguage && language.split('-')[0] === prefix) {
                    matchingLanguage = language;
                }
            });
            key = matchingLanguage || fallbackLanguage || 'en-US';
        }
        chooseCulture(key);
    };

    /**
     * This function allow the user to set a new culture with a fallback if
     * the culture does not exist. If no fallback culture is provided,
     * it falls back to "en-US".
     */
    numbro.setCulture = function(newCulture, fallbackCulture) {
        var key = newCulture,
            suffix = newCulture.split('-')[1],
            matchingCulture = null;
        if (!cultures[key]) {
            if (suffix) {
                Object.keys(cultures).forEach(function(language) {
                    if (!matchingCulture && language.split('-')[1] === suffix) {
                        matchingCulture = language;
                    }
                });
            }

            key = matchingCulture || fallbackCulture || 'en-US';
        }
        chooseCulture(key);
    };

    /**
     * This function will load languages and then set the global language.  If
     * no arguments are passed in, it will simply return the current global
     * language key.
     *
     * @deprecated Since in version 1.6.0. It will be deleted in version 2.0
     * `culture` should be used instead.
     */
    numbro.language = function(key, values) {
        console.warn('`language` is deprecated since version 1.6.0. Use `culture` instead');

        if (!key) {
            return currentCulture;
        }

        if (key && !values) {
            if (!languages[key]) {
                throw new Error('Unknown language : ' + key);
            }
            chooseCulture(key);
        }

        if (values || !languages[key]) {
            setCulture(key, values);
        }

        return numbro;
    };

    /**
     * This function will load cultures and then set the global culture.  If
     * no arguments are passed in, it will simply return the current global
     * culture code.
     */
    numbro.culture = function(code, values) {
        if (!code) {
            return currentCulture;
        }

        if (code && !values) {
            if (!cultures[code]) {
                throw new Error('Unknown culture : ' + code);
            }
            chooseCulture(code);
        }

        if (values || !cultures[code]) {
            setCulture(code, values);
        }

        return numbro;
    };

    /**
     * This function provides access to the loaded language data.  If
     * no arguments are passed in, it will simply return the current
     * global language object.
     *
     * @deprecated Since in version 1.6.0. It will be deleted in version 2.0
     * `culture` should be used instead.
     */
    numbro.languageData = function(key) {
        console.warn('`languageData` is deprecated since version 1.6.0. Use `cultureData` instead');

        if (!key) {
            return languages[currentCulture];
        }

        if (!languages[key]) {
            throw new Error('Unknown language : ' + key);
        }

        return languages[key];
    };

    /**
     * This function provides access to the loaded culture data.  If
     * no arguments are passed in, it will simply return the current
     * global culture object.
     */
    numbro.cultureData = function(code) {
        if (!code) {
            return cultures[currentCulture];
        }

        if (!cultures[code]) {
            throw new Error('Unknown culture : ' + code);
        }

        return cultures[code];
    };

    numbro.culture('en-US', enUS);

    /**
     * @deprecated Since in version 1.6.0. It will be deleted in version 2.0
     * `cultures` should be used instead.
     */
    numbro.languages = function() {
        console.warn('`languages` is deprecated since version 1.6.0. Use `cultures` instead');

        return languages;
    };

    numbro.cultures = function() {
        return cultures;
    };

    numbro.zeroFormat = function(format) {
        zeroFormat = typeof(format) === 'string' ? format : null;
    };

    numbro.defaultFormat = function(format) {
        defaultFormat = typeof(format) === 'string' ? format : '0.0';
    };

    numbro.defaultCurrencyFormat = function (format) {
        defaultCurrencyFormat = typeof(format) === 'string' ? format : '0$';
    };

    numbro.validate = function(val, culture) {

        var _decimalSep,
            _thousandSep,
            _currSymbol,
            _valArray,
            _abbrObj,
            _thousandRegEx,
            cultureData,
            temp;

        //coerce val to string
        if (typeof val !== 'string') {
            val += '';
            if (console.warn) {
                console.warn('Numbro.js: Value is not string. It has been co-erced to: ', val);
            }
        }

        //trim whitespaces from either sides
        val = val.trim();

        //replace the initial '+' or '-' sign if present
        val = val.replace(/^[+-]?/, '');

        //if val is just digits return true
        if ( !! val.match(/^\d+$/)) {
            return true;
        }

        //if val is empty return false
        if (val === '') {
            return false;
        }

        //get the decimal and thousands separator from numbro.cultureData
        try {
            //check if the culture is understood by numbro. if not, default it to current culture
            cultureData = numbro.cultureData(culture);
        } catch (e) {
            cultureData = numbro.cultureData(numbro.culture());
        }

        //setup the delimiters and currency symbol based on culture
        _currSymbol = cultureData.currency.symbol;
        _abbrObj = cultureData.abbreviations;
        _decimalSep = cultureData.delimiters.decimal;
        if (cultureData.delimiters.thousands === '.') {
            _thousandSep = '\\.';
        } else {
            _thousandSep = cultureData.delimiters.thousands;
        }

        // validating currency symbol
        temp = val.match(/^[^\d\.\,]+/);
        if (temp !== null) {
            val = val.substr(1);
            if (temp[0] !== _currSymbol) {
                return false;
            }
        }

        //validating abbreviation symbol
        temp = val.match(/[^\d]+$/);
        if (temp !== null) {
            val = val.slice(0, -1);
            if (temp[0] !== _abbrObj.thousand && temp[0] !== _abbrObj.million &&
                    temp[0] !== _abbrObj.billion && temp[0] !== _abbrObj.trillion) {
                return false;
            }
        }

        _thousandRegEx = new RegExp(_thousandSep + '{2}');

        if (!val.match(/[^\d.,]/g)) {
            _valArray = val.split(_decimalSep);
            if (_valArray.length > 2) {
                return false;
            } else {
                if (_valArray.length < 2) {
                    return ( !! _valArray[0].match(/^\d+.*\d$/) && !_valArray[0].match(_thousandRegEx));
                } else {
                    if (_valArray[0] === '') {
                        // for values without leading zero eg. .984
                        return (!_valArray[0].match(_thousandRegEx) &&
                            !!_valArray[1].match(/^\d+$/));

                    } else if (_valArray[0].length === 1) {
                        return ( !! _valArray[0].match(/^\d+$/) &&
                            !_valArray[0].match(_thousandRegEx) &&
                            !! _valArray[1].match(/^\d+$/));
                    } else {
                        return ( !! _valArray[0].match(/^\d+.*\d$/) &&
                            !_valArray[0].match(_thousandRegEx) &&
                            !! _valArray[1].match(/^\d+$/));
                    }
                }
            }
        }

        return false;
    };

    /**
     * * @deprecated Since in version 1.6.0. It will be deleted in version 2.0
     * `loadCulturesInNode` should be used instead.
     */
    numbro.loadLanguagesInNode = function() {
        console.warn('`loadLanguagesInNode` is deprecated since version 1.6.0. Use `loadCulturesInNode` instead');

        numbro.loadCulturesInNode();
    };

    numbro.loadCulturesInNode = function() {
        // TODO: Rename the folder in 2.0.0
        var cultures = __webpack_require__(305);

        for(var langLocaleCode in cultures) {
            if(langLocaleCode) {
                numbro.culture(langLocaleCode, cultures[langLocaleCode]);
            }
        }
    };

    /************************************
        Helpers
    ************************************/

    function setCulture(code, values) {
        cultures[code] = values;
    }

    function chooseCulture(code) {
        currentCulture = code;
        var defaults = cultures[code].defaults;
        if (defaults && defaults.format) {
            numbro.defaultFormat(defaults.format);
        }
        if (defaults && defaults.currencyFormat) {
            numbro.defaultCurrencyFormat(defaults.currencyFormat);
        }
    }

    function inNodejsRuntime() {
        return (typeof process !== 'undefined') &&
            (process.browser === undefined) &&
            process.title &&
            (
                process.title.indexOf('node') !== -1 ||
                process.title.indexOf('meteor-tool') > 0 ||
                process.title === 'grunt' ||
                process.title === 'gulp'
            ) &&
            ("function" !== 'undefined');
    }

    /************************************
        Floating-point helpers
    ************************************/

    // The floating-point helper functions and implementation
    // borrows heavily from sinful.js: http://guipn.github.io/sinful.js/

    /**
     * Array.prototype.reduce for browsers that don't support it
     * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce#Compatibility
     */
    if ('function' !== typeof Array.prototype.reduce) {
        Array.prototype.reduce = function(callback, optInitialValue) {

            if (null === this || 'undefined' === typeof this) {
                // At the moment all modern browsers, that support strict mode, have
                // native implementation of Array.prototype.reduce. For instance, IE8
                // does not support strict mode, so this check is actually useless.
                throw new TypeError('Array.prototype.reduce called on null or undefined');
            }

            if ('function' !== typeof callback) {
                throw new TypeError(callback + ' is not a function');
            }

            var index,
                value,
                length = this.length >>> 0,
                isValueSet = false;

            if (1 < arguments.length) {
                value = optInitialValue;
                isValueSet = true;
            }

            for (index = 0; length > index; ++index) {
                if (this.hasOwnProperty(index)) {
                    if (isValueSet) {
                        value = callback(value, this[index], index, this);
                    } else {
                        value = this[index];
                        isValueSet = true;
                    }
                }
            }

            if (!isValueSet) {
                throw new TypeError('Reduce of empty array with no initial value');
            }

            return value;
        };
    }


    /**
     * Computes the multiplier necessary to make x >= 1,
     * effectively eliminating miscalculations caused by
     * finite precision.
     */
    function multiplier(x) {
        var parts = x.toString().split('.');
        if (parts.length < 2) {
            return 1;
        }
        return Math.pow(10, parts[1].length);
    }

    /**
     * Given a variable number of arguments, returns the maximum
     * multiplier that must be used to normalize an operation involving
     * all of them.
     */
    function correctionFactor() {
        var args = Array.prototype.slice.call(arguments);
        return args.reduce(function(prev, next) {
            var mp = multiplier(prev),
                mn = multiplier(next);
            return mp > mn ? mp : mn;
        }, -Infinity);
    }

    /************************************
        Numbro Prototype
    ************************************/


    numbro.fn = Numbro.prototype = {

        clone: function() {
            return numbro(this);
        },

        format: function(inputString, roundingFunction) {
            return formatNumbro(this,
                inputString ? inputString : defaultFormat,
                (roundingFunction !== undefined) ? roundingFunction : Math.round
            );
        },

        formatCurrency: function(inputString, roundingFunction) {
            return formatCurrency(this,
                cultures[currentCulture].currency.symbol,
                inputString ? inputString : defaultCurrencyFormat,
                (roundingFunction !== undefined) ? roundingFunction : Math.round
            );
        },

        formatForeignCurrency: function(currencySymbol, inputString, roundingFunction) {
            return formatForeignCurrency(this,
                currencySymbol,
                inputString ? inputString : defaultCurrencyFormat,
                (roundingFunction !== undefined) ? roundingFunction : Math.round
            );
        },

        unformat: function(inputString) {
            if (typeof inputString === 'number') {
                return inputString;
            } else if (typeof inputString === 'string') {
                var result = unformatNumbro(this, inputString);

                // Any unparseable string (represented as NaN in the result) is
                // converted into undefined.
                return isNaN(result) ? undefined : result;
            } else {
                return undefined;
            }
        },

        binaryByteUnits: function() {
            return formatByteUnits(this._value, bytes.binary.suffixes, bytes.binary.scale).suffix;
        },

        byteUnits: function() {
            return formatByteUnits(this._value, bytes.general.suffixes, bytes.general.scale).suffix;
        },

        decimalByteUnits: function() {
            return formatByteUnits(this._value, bytes.decimal.suffixes, bytes.decimal.scale).suffix;
        },

        value: function() {
            return this._value;
        },

        valueOf: function() {
            return this._value;
        },

        set: function(value) {
            this._value = Number(value);
            return this;
        },

        add: function(value) {
            var corrFactor = correctionFactor.call(null, this._value, value);

            function cback(accum, curr) {
                return accum + corrFactor * curr;
            }
            this._value = [this._value, value].reduce(cback, 0) / corrFactor;
            return this;
        },

        subtract: function(value) {
            var corrFactor = correctionFactor.call(null, this._value, value);

            function cback(accum, curr) {
                return accum - corrFactor * curr;
            }
            this._value = [value].reduce(cback, this._value * corrFactor) / corrFactor;
            return this;
        },

        multiply: function(value) {
            function cback(accum, curr) {
                var corrFactor = correctionFactor(accum, curr),
                    result = accum * corrFactor;
                result *= curr * corrFactor;
                result /= corrFactor * corrFactor;
                return result;
            }
            this._value = [this._value, value].reduce(cback, 1);
            return this;
        },

        divide: function(value) {
            function cback(accum, curr) {
                var corrFactor = correctionFactor(accum, curr);
                return (accum * corrFactor) / (curr * corrFactor);
            }
            this._value = [this._value, value].reduce(cback);
            return this;
        },

        difference: function(value) {
            return Math.abs(numbro(this._value).subtract(value).value());
        }

    };

    /************************************
        Exposing Numbro
    ************************************/

    if (inNodejsRuntime()) {
        //Todo: Rename the folder in 2.0.0
        numbro.loadCulturesInNode();
    }

    // CommonJS module is defined
    if (hasModule) {
        module.exports = numbro;
    } else {
        /*global ender:false */
        if (typeof ender === 'undefined') {
            // here, `this` means `window` in the browser, or `global` on the server
            // add `numbro` as a global object via a string identifier,
            // for Closure Compiler 'advanced' mode
            this.numbro = numbro;
        }

        /*global define:false */
        if (true) {
            !(__WEBPACK_AMD_DEFINE_ARRAY__ = [], __WEBPACK_AMD_DEFINE_RESULT__ = function() {
                return numbro;
            }.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),
				__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
        }
    }

}.call(typeof window === 'undefined' ? this : window));


/*** EXPORTS FROM exports-to-window-loader ***/
window['numbro'] = __webpack_require__(52);

/***/ }),
/* 53 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


exports.__esModule = true;
exports.default = staticRegister;

function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }

var collection = exports.collection = new Map();

function staticRegister() {
  var namespace = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'common';

  if (!collection.has(namespace)) {
    collection.set(namespace, new Map());
  }
  var subCollection = collection.get(namespace);

  /**
   * Register an item to the collection. If the item under the same was exist earlier then this item will be replaced with new one.
   *
   * @param {String} name Identification of the item.
   * @param {*} item Item to save in the collection.
   */
  function register(name, item) {
    subCollection.set(name, item);
  }

  /**
   * Retrieve the item from the collection.
   *
   * @param {String} name Identification of the item.
   * @returns {*} Returns item which was saved in the collection.
   */
  function getItem(name) {
    return subCollection.get(name);
  }

  /**
   * Check if item under specyfied name is exists.
   *
   * @param {String} name Identification of the item.
   * @returns {Boolean} Returns `true` or `false` depends on if element exists in the collection.
   */
  function hasItem(name) {
    return subCollection.has(name);
  }

  /**
   * Retrieve list of names registered from the collection.
   *
   * @returns {Array} Returns an array of strings with all names under which objects are stored.
   */
  function getNames() {
    return [].concat(_toConsumableArray(subCollection.keys()));
  }

  /**
   * Retrieve all registered values from the collection.
   *
   * @returns {Array} Returns an array with all values stored in the collection.
   */
  function getValues() {
    return [].concat(_toConsumableArray(subCollection.values()));
  }

  return {
    register: register,
    getItem: getItem,
    hasItem: hasItem,
    getNames: getNames,
    getValues: getValues
  };
}

/***/ }),
/* 54 */
/***/ (function(module, exports) {

module.exports = function (it) {
  if (typeof it != 'function') throw TypeError(it + ' is not a function!');
  return it;
};


/***/ }),
/* 55 */
/***/ (function(module, exports) {

module.exports = function (it, Constructor, name, forbiddenField) {
  if (!(it instanceof Constructor) || (forbiddenField !== undefined && forbiddenField in it)) {
    throw TypeError(name + ': incorrect invocation!');
  } return it;
};


/***/ }),
/* 56 */
/***/ (function(module, exports, __webpack_require__) {

// 0 -> Array#forEach
// 1 -> Array#map
// 2 -> Array#filter
// 3 -> Array#some
// 4 -> Array#every
// 5 -> Array#find
// 6 -> Array#findIndex
var ctx = __webpack_require__(30);
var IObject = __webpack_require__(78);
var toObject = __webpack_require__(40);
var toLength = __webpack_require__(21);
var asc = __webpack_require__(392);
module.exports = function (TYPE, $create) {
  var IS_MAP = TYPE == 1;
  var IS_FILTER = TYPE == 2;
  var IS_SOME = TYPE == 3;
  var IS_EVERY = TYPE == 4;
  var IS_FIND_INDEX = TYPE == 6;
  var NO_HOLES = TYPE == 5 || IS_FIND_INDEX;
  var create = $create || asc;
  return function ($this, callbackfn, that) {
    var O = toObject($this);
    var self = IObject(O);
    var f = ctx(callbackfn, that, 3);
    var length = toLength(self.length);
    var index = 0;
    var result = IS_MAP ? create($this, length) : IS_FILTER ? create($this, 0) : undefined;
    var val, res;
    for (;length > index; index++) if (NO_HOLES || index in self) {
      val = self[index];
      res = f(val, index, O);
      if (TYPE) {
        if (IS_MAP) result[index] = res;   // map
        else if (res) switch (TYPE) {
          case 3: return true;             // some
          case 5: return val;              // find
          case 6: return index;            // findIndex
          case 2: result.push(val);        // filter
        } else if (IS_EVERY) return false; // every
      }
    }
    return IS_FIND_INDEX ? -1 : IS_SOME || IS_EVERY ? IS_EVERY : result;
  };
};


/***/ }),
/* 57 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";

var global = __webpack_require__(10);
var $export = __webpack_require__(1);
var redefine = __webpack_require__(32);
var redefineAll = __webpack_require__(62);
var meta = __webpack_require__(47);
var forOf = __webpack_require__(59);
var anInstance = __webpack_require__(55);
var isObject = __webpack_require__(12);
var fails = __webpack_require__(25);
var $iterDetect = __webpack_require__(79);
var setToStringTag = __webpack_require__(50);
var inheritIfRequired = __webpack_require__(395);

module.exports = function (NAME, wrapper, methods, common, IS_MAP, IS_WEAK) {
  var Base = global[NAME];
  var C = Base;
  var ADDER = IS_MAP ? 'set' : 'add';
  var proto = C && C.prototype;
  var O = {};
  var fixMethod = function (KEY) {
    var fn = proto[KEY];
    redefine(proto, KEY,
      KEY == 'delete' ? function (a) {
        return IS_WEAK && !isObject(a) ? false : fn.call(this, a === 0 ? 0 : a);
      } : KEY == 'has' ? function has(a) {
        return IS_WEAK && !isObject(a) ? false : fn.call(this, a === 0 ? 0 : a);
      } : KEY == 'get' ? function get(a) {
        return IS_WEAK && !isObject(a) ? undefined : fn.call(this, a === 0 ? 0 : a);
      } : KEY == 'add' ? function add(a) { fn.call(this, a === 0 ? 0 : a); return this; }
        : function set(a, b) { fn.call(this, a === 0 ? 0 : a, b); return this; }
    );
  };
  if (typeof C != 'function' || !(IS_WEAK || proto.forEach && !fails(function () {
    new C().entries().next();
  }))) {
    // create collection constructor
    C = common.getConstructor(wrapper, NAME, IS_MAP, ADDER);
    redefineAll(C.prototype, methods);
    meta.NEED = true;
  } else {
    var instance = new C();
    // early implementations not supports chaining
    var HASNT_CHAINING = instance[ADDER](IS_WEAK ? {} : -0, 1) != instance;
    // V8 ~  Chromium 40- weak-collections throws on primitives, but should return false
    var THROWS_ON_PRIMITIVES = fails(function () { instance.has(1); });
    // most early implementations doesn't supports iterables, most modern - not close it correctly
    var ACCEPT_ITERABLES = $iterDetect(function (iter) { new C(iter); }); // eslint-disable-line no-new
    // for early implementations -0 and +0 not the same
    var BUGGY_ZERO = !IS_WEAK && fails(function () {
      // V8 ~ Chromium 42- fails only with 5+ elements
      var $instance = new C();
      var index = 5;
      while (index--) $instance[ADDER](index, index);
      return !$instance.has(-0);
    });
    if (!ACCEPT_ITERABLES) {
      C = wrapper(function (target, iterable) {
        anInstance(target, C, NAME);
        var that = inheritIfRequired(new Base(), target, C);
        if (iterable != undefined) forOf(iterable, IS_MAP, that[ADDER], that);
        return that;
      });
      C.prototype = proto;
      proto.constructor = C;
    }
    if (THROWS_ON_PRIMITIVES || BUGGY_ZERO) {
      fixMethod('delete');
      fixMethod('has');
      IS_MAP && fixMethod('get');
    }
    if (BUGGY_ZERO || HASNT_CHAINING) fixMethod(ADDER);
    // weak collections should not contains .clear method
    if (IS_WEAK && proto.clear) delete proto.clear;
  }

  setToStringTag(C, NAME);

  O[NAME] = C;
  $export($export.G + $export.W + $export.F * (C != Base), O);

  if (!IS_WEAK) common.setStrong(C, NAME, IS_MAP);

  return C;
};


/***/ }),
/* 58 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";

var hide = __webpack_require__(31);
var redefine = __webpack_require__(32);
var fails = __webpack_require__(25);
var defined = __webpack_require__(33);
var wks = __webpack_require__(8);

module.exports = function (KEY, length, exec) {
  var SYMBOL = wks(KEY);
  var fns = exec(defined, SYMBOL, ''[KEY]);
  var strfn = fns[0];
  var rxfn = fns[1];
  if (fails(function () {
    var O = {};
    O[SYMBOL] = function () { return 7; };
    return ''[KEY](O) != 7;
  })) {
    redefine(String.prototype, KEY, strfn);
    hide(RegExp.prototype, SYMBOL, length == 2
      // 21.2.5.8 RegExp.prototype[@@replace](string, replaceValue)
      // 21.2.5.11 RegExp.prototype[@@split](string, limit)
      ? function (string, arg) { return rxfn.call(string, this, arg); }
      // 21.2.5.6 RegExp.prototype[@@match](string)
      // 21.2.5.9 RegExp.prototype[@@search](string)
      : function (string) { return rxfn.call(string, this); }
    );
  }
};


/***/ }),
/* 59 */
/***/ (function(module, exports, __webpack_require__) {

var ctx = __webpack_require__(30);
var call = __webpack_require__(280);
var isArrayIter = __webpack_require__(276);
var anObject = __webpack_require__(17);
var toLength = __webpack_require__(21);
var getIterFn = __webpack_require__(292);
var BREAK = {};
var RETURN = {};
var exports = module.exports = function (iterable, entries, fn, that, ITERATOR) {
  var iterFn = ITERATOR ? function () { return iterable; } : getIterFn(iterable);
  var f = ctx(fn, that, entries ? 2 : 1);
  var index = 0;
  var length, step, iterator, result;
  if (typeof iterFn != 'function') throw TypeError(iterable + ' is not iterable!');
  // fast case for arrays with default iterator
  if (isArrayIter(iterFn)) for (length = toLength(iterable.length); length > index; index++) {
    result = entries ? f(anObject(step = iterable[index])[0], step[1]) : f(iterable[index]);
    if (result === BREAK || result === RETURN) return result;
  } else for (iterator = iterFn.call(iterable); !(step = iterator.next()).done;) {
    result = call(iterator, f, step.value, entries);
    if (result === BREAK || result === RETURN) return result;
  }
};
exports.BREAK = BREAK;
exports.RETURN = RETURN;


/***/ }),
/* 60 */
/***/ (function(module, exports) {

module.exports = false;


/***/ }),
/* 61 */
/***/ (function(module, exports) {

exports.f = Object.getOwnPropertySymbols;


/***/ }),
/* 62 */
/***/ (function(module, exports, __webpack_require__) {

var redefine = __webpack_require__(32);
module.exports = function (target, src, safe) {
  for (var key in src) redefine(target, key, src[key], safe);
  return target;
};


/***/ }),
/* 63 */
/***/ (function(module, exports, __webpack_require__) {

var toInteger = __webpack_require__(64);
var max = Math.max;
var min = Math.min;
module.exports = function (index, length) {
  index = toInteger(index);
  return index < 0 ? max(index + length, 0) : min(index, length);
};


/***/ }),
/* 64 */
/***/ (function(module, exports) {

// 7.1.4 ToInteger
var ceil = Math.ceil;
var floor = Math.floor;
module.exports = function (it) {
  return isNaN(it = +it) ? 0 : (it > 0 ? floor : ceil)(it);
};


/***/ }),
/* 65 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


exports.__esModule = true;
exports.getRegisteredCellTypes = exports.getRegisteredCellTypeNames = exports.hasCellType = exports.getCellType = exports.registerCellType = undefined;

var _staticRegister2 = __webpack_require__(53);

var _staticRegister3 = _interopRequireDefault(_staticRegister2);

var _editors = __webpack_require__(13);

var _renderers = __webpack_require__(6);

var _validators = __webpack_require__(24);

var _autocompleteType = __webpack_require__(312);

var _autocompleteType2 = _interopRequireDefault(_autocompleteType);

var _checkboxType = __webpack_require__(313);

var _checkboxType2 = _interopRequireDefault(_checkboxType);

var _dateType = __webpack_require__(314);

var _dateType2 = _interopRequireDefault(_dateType);

var _dropdownType = __webpack_require__(315);

var _dropdownType2 = _interopRequireDefault(_dropdownType);

var _handsontableType = __webpack_require__(316);

var _handsontableType2 = _interopRequireDefault(_handsontableType);

var _numericType = __webpack_require__(317);

var _numericType2 = _interopRequireDefault(_numericType);

var _passwordType = __webpack_require__(318);

var _passwordType2 = _interopRequireDefault(_passwordType);

var _textType = __webpack_require__(319);

var _textType2 = _interopRequireDefault(_textType);

var _timeType = __webpack_require__(320);

var _timeType2 = _interopRequireDefault(_timeType);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

var _staticRegister = (0, _staticRegister3.default)('cellTypes'),
    register = _staticRegister.register,
    getItem = _staticRegister.getItem,
    hasItem = _staticRegister.hasItem,
    getNames = _staticRegister.getNames,
    getValues = _staticRegister.getValues;

_register('autocomplete', _autocompleteType2.default);
_register('checkbox', _checkboxType2.default);
_register('date', _dateType2.default);
_register('dropdown', _dropdownType2.default);
_register('handsontable', _handsontableType2.default);
_register('numeric', _numericType2.default);
_register('password', _passwordType2.default);
_register('text', _textType2.default);
_register('time', _timeType2.default);

/**
 * Retrieve cell type object.
 *
 * @param {String} name Cell type identification.
 * @returns {Object} Returns cell type object.
 */
function _getItem(name) {
  if (!hasItem(name)) {
    throw Error('You declared cell type "' + name + '" as a string that is not mapped to a known object.\n                 Cell type must be an object or a string mapped to an object registered by "Handsontable.cellTypes.registerCellType" method');
  }

  return getItem(name);
}

/**
 * Register cell type under specified name.
 *
 * @param {String} name Cell type identification.
 * @param {Object} type An object with contains keys (eq: `editor`, `renderer`, `validator`) which describes specified behaviour of the cell.
 */
function _register(name, type) {
  var editor = type.editor,
      renderer = type.renderer,
      validator = type.validator;


  if (editor) {
    (0, _editors.registerEditor)(name, editor);
  }
  if (renderer) {
    (0, _renderers.registerRenderer)(name, renderer);
  }
  if (validator) {
    (0, _validators.registerValidator)(name, validator);
  }

  register(name, type);
}

exports.registerCellType = _register;
exports.getCellType = _getItem;
exports.hasCellType = hasItem;
exports.getRegisteredCellTypeNames = getNames;
exports.getRegisteredCellTypes = getValues;

/***/ }),
/* 66 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


exports.__esModule = true;

var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }();

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

exports.default = Core;

var _numbro = __webpack_require__(52);

var _numbro2 = _interopRequireDefault(_numbro);

var _element = __webpack_require__(0);

var _setting = __webpack_require__(68);

var _function = __webpack_require__(35);

var _mixed = __webpack_require__(23);

var _browser = __webpack_require__(22);

var _dataMap = __webpack_require__(321);

var _dataMap2 = _interopRequireDefault(_dataMap);

var _editorManager = __webpack_require__(323);

var _editorManager2 = _interopRequireDefault(_editorManager);

var _eventManager = __webpack_require__(4);

var _eventManager2 = _interopRequireDefault(_eventManager);

var _object = __webpack_require__(3);

var _array = __webpack_require__(2);

var _plugins = __webpack_require__(9);

var _renderers = __webpack_require__(6);

var _validators = __webpack_require__(24);

var _string = __webpack_require__(28);

var _number = __webpack_require__(5);

var _tableView = __webpack_require__(383);

var _tableView2 = _interopRequireDefault(_tableView);

var _dataSource = __webpack_require__(322);

var _dataSource2 = _interopRequireDefault(_dataSource);

var _data = __webpack_require__(67);

var _recordTranslator = __webpack_require__(268);

var _rootInstance = __webpack_require__(90);

var _src = __webpack_require__(14);

var _pluginHooks = __webpack_require__(11);

var _pluginHooks2 = _interopRequireDefault(_pluginHooks);

var _defaultSettings = __webpack_require__(88);

var _defaultSettings2 = _interopRequireDefault(_defaultSettings);

var _cellTypes = __webpack_require__(65);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }

var activeGuid = null;

/**
 * Handsontable constructor
 *
 * @core
 * @dependencies numbro
 * @constructor Core
 * @description
 *
 * After Handsontable is constructed, you can modify the grid behavior using the available public methods.
 *
 * ---
 * ## How to call methods
 *
 * These are 2 equal ways to call a Handsontable method:
 *
 * ```js
 * // all following examples assume that you constructed Handsontable like this
 * var ht = new Handsontable(document.getElementById('example1'), options);
 *
 * // now, to use setDataAtCell method, you can either:
 * ht.setDataAtCell(0, 0, 'new value');
 * ```
 *
 * Alternatively, you can call the method using jQuery wrapper (__obsolete__, requires initialization using our jQuery guide
 * ```js
 *   $('#example1').handsontable('setDataAtCell', 0, 0, 'new value');
 * ```
 * ---
 */
function Core(rootElement, userSettings) {
  var rootInstanceSymbol = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;

  var priv,
      datamap,
      dataSource,
      grid,
      selection,
      editorManager,
      instance = this,
      GridSettings = function GridSettings() {},
      eventManager = new _eventManager2.default(instance);

  (0, _object.extend)(GridSettings.prototype, _defaultSettings2.default.prototype); // create grid settings as a copy of default settings
  (0, _object.extend)(GridSettings.prototype, userSettings); // overwrite defaults with user settings
  (0, _object.extend)(GridSettings.prototype, expandType(userSettings));

  if ((0, _rootInstance.hasValidParameter)(rootInstanceSymbol)) {
    (0, _rootInstance.registerAsRootInstance)(this);
  }

  this.rootElement = rootElement;
  this.isHotTableEnv = (0, _element.isChildOfWebComponentTable)(this.rootElement);
  _eventManager2.default.isHotTableEnv = this.isHotTableEnv;

  this.container = document.createElement('div');
  this.renderCall = false;

  rootElement.insertBefore(this.container, rootElement.firstChild);

  if (undefined !== '\x63\x65' && (0, _rootInstance.isRootInstance)(this)) {
    (0, _mixed._injectProductInfo)(userSettings.licenseKey, rootElement);
  }

  this.guid = 'ht_' + (0, _string.randomString)(); // this is the namespace for global events

  var recordTranslator = (0, _recordTranslator.getTranslator)(instance);

  dataSource = new _dataSource2.default(instance);

  if (!this.rootElement.id || this.rootElement.id.substring(0, 3) === 'ht_') {
    this.rootElement.id = this.guid; // if root element does not have an id, assign a random id
  }
  priv = {
    cellSettings: [],
    columnSettings: [],
    columnsSettingConflicts: ['data', 'width'],
    settings: new GridSettings(), // current settings instance
    selRange: null, // exposed by public method `getSelectedRange`
    isPopulated: null,
    scrollable: null,
    firstRun: true
  };

  grid = {
    /**
     * Inserts or removes rows and columns
     *
     * @memberof Core#
     * @function alter
     * @private
     * @param {String} action Possible values: "insert_row", "insert_col", "remove_row", "remove_col"
     * @param {Number} index
     * @param {Number} amount
     * @param {String} [source] Optional. Source of hook runner.
     * @param {Boolean} [keepEmptyRows] Optional. Flag for preventing deletion of empty rows.
     */
    alter: function alter(action, index, amount, source, keepEmptyRows) {
      var delta;

      amount = amount || 1;

      function spliceWith(data, index, count, toInject) {
        var valueFactory = function valueFactory() {
          var result = void 0;

          if (toInject === 'array') {
            result = [];
          } else if (toInject === 'object') {
            result = {};
          }

          return result;
        };
        var spliceArgs = (0, _array.arrayMap)(new Array(count), function () {
          return valueFactory();
        });

        spliceArgs.unshift(index, 0);
        data.splice.apply(data, _toConsumableArray(spliceArgs));
      }

      /* eslint-disable no-case-declarations */
      switch (action) {
        case 'insert_row':

          var numberOfSourceRows = instance.countSourceRows();

          if (instance.getSettings().maxRows === numberOfSourceRows) {
            return;
          }

          index = (0, _mixed.isDefined)(index) ? index : numberOfSourceRows;

          delta = datamap.createRow(index, amount, source);
          spliceWith(priv.cellSettings, index, amount, 'array');

          if (delta) {
            if (selection.isSelected() && priv.selRange.from.row >= index) {
              priv.selRange.from.row += delta;
              selection.transformEnd(delta, 0); // will call render() internally
            } else {
              selection.refreshBorders(); // it will call render and prepare methods
            }
          }
          break;

        case 'insert_col':
          delta = datamap.createCol(index, amount, source);

          for (var row = 0, len = instance.countSourceRows(); row < len; row++) {
            if (priv.cellSettings[row]) {
              spliceWith(priv.cellSettings[row], index, amount);
            }
          }

          if (delta) {
            if (Array.isArray(instance.getSettings().colHeaders)) {
              var spliceArray = [index, 0];
              spliceArray.length += delta; // inserts empty (undefined) elements at the end of an array
              Array.prototype.splice.apply(instance.getSettings().colHeaders, spliceArray); // inserts empty (undefined) elements into the colHeader array
            }

            if (selection.isSelected() && priv.selRange.from.col >= index) {
              priv.selRange.from.col += delta;
              selection.transformEnd(0, delta); // will call render() internally
            } else {
              selection.refreshBorders(); // it will call render and prepare methods
            }
          }
          break;

        case 'remove_row':
          datamap.removeRow(index, amount, source);
          priv.cellSettings.splice(index, amount);

          var totalRows = instance.countRows();
          var fixedRowsTop = instance.getSettings().fixedRowsTop;
          if (fixedRowsTop >= index + 1) {
            instance.getSettings().fixedRowsTop -= Math.min(amount, fixedRowsTop - index);
          }

          var fixedRowsBottom = instance.getSettings().fixedRowsBottom;
          if (fixedRowsBottom && index >= totalRows - fixedRowsBottom) {
            instance.getSettings().fixedRowsBottom -= Math.min(amount, fixedRowsBottom);
          }

          grid.adjustRowsAndCols();
          selection.refreshBorders(); // it will call render and prepare methods
          break;

        case 'remove_col':
          var visualColumnIndex = recordTranslator.toPhysicalColumn(index);

          datamap.removeCol(index, amount, source);

          for (var _row = 0, _len = instance.countSourceRows(); _row < _len; _row++) {
            if (priv.cellSettings[_row]) {
              // if row hasn't been rendered it wouldn't have cellSettings
              priv.cellSettings[_row].splice(visualColumnIndex, amount);
            }
          }
          var fixedColumnsLeft = instance.getSettings().fixedColumnsLeft;

          if (fixedColumnsLeft >= index + 1) {
            instance.getSettings().fixedColumnsLeft -= Math.min(amount, fixedColumnsLeft - index);
          }

          if (Array.isArray(instance.getSettings().colHeaders)) {
            if (typeof visualColumnIndex === 'undefined') {
              visualColumnIndex = -1;
            }
            instance.getSettings().colHeaders.splice(visualColumnIndex, amount);
          }

          grid.adjustRowsAndCols();
          selection.refreshBorders(); // it will call render and prepare methods

          break;
        default:
          throw new Error('There is no such action "' + action + '"');
      }

      if (!keepEmptyRows) {
        grid.adjustRowsAndCols(); // makes sure that we did not add rows that will be removed in next refresh
      }
    },


    /**
     * Makes sure there are empty rows at the bottom of the table
     */
    adjustRowsAndCols: function adjustRowsAndCols() {
      if (priv.settings.minRows) {
        // should I add empty rows to data source to meet minRows?
        var rows = instance.countRows();

        if (rows < priv.settings.minRows) {
          for (var r = 0, minRows = priv.settings.minRows; r < minRows - rows; r++) {
            datamap.createRow(instance.countRows(), 1, 'auto');
          }
        }
      }
      if (priv.settings.minSpareRows) {
        var emptyRows = instance.countEmptyRows(true);

        // should I add empty rows to meet minSpareRows?
        if (emptyRows < priv.settings.minSpareRows) {
          for (; emptyRows < priv.settings.minSpareRows && instance.countSourceRows() < priv.settings.maxRows; emptyRows++) {
            datamap.createRow(instance.countRows(), 1, 'auto');
          }
        }
      }
      {
        var emptyCols = void 0;

        // count currently empty cols
        if (priv.settings.minCols || priv.settings.minSpareCols) {
          emptyCols = instance.countEmptyCols(true);
        }

        // should I add empty cols to meet minCols?
        if (priv.settings.minCols && !priv.settings.columns && instance.countCols() < priv.settings.minCols) {
          for (; instance.countCols() < priv.settings.minCols; emptyCols++) {
            datamap.createCol(instance.countCols(), 1, 'auto');
          }
        }
        // should I add empty cols to meet minSpareCols?
        if (priv.settings.minSpareCols && !priv.settings.columns && instance.dataType === 'array' && emptyCols < priv.settings.minSpareCols) {
          for (; emptyCols < priv.settings.minSpareCols && instance.countCols() < priv.settings.maxCols; emptyCols++) {
            datamap.createCol(instance.countCols(), 1, 'auto');
          }
        }
      }
      var rowCount = instance.countRows();
      var colCount = instance.countCols();

      if (rowCount === 0 || colCount === 0) {
        selection.deselect();
      }

      if (selection.isSelected()) {
        var selectionChanged = false;
        var fromRow = priv.selRange.from.row;
        var fromCol = priv.selRange.from.col;
        var toRow = priv.selRange.to.row;
        var toCol = priv.selRange.to.col;

        // if selection is outside, move selection to last row
        if (fromRow > rowCount - 1) {
          fromRow = rowCount - 1;
          selectionChanged = true;

          if (toRow > fromRow) {
            toRow = fromRow;
          }
        } else if (toRow > rowCount - 1) {
          toRow = rowCount - 1;
          selectionChanged = true;

          if (fromRow > toRow) {
            fromRow = toRow;
          }
        }
        // if selection is outside, move selection to last row
        if (fromCol > colCount - 1) {
          fromCol = colCount - 1;
          selectionChanged = true;

          if (toCol > fromCol) {
            toCol = fromCol;
          }
        } else if (toCol > colCount - 1) {
          toCol = colCount - 1;
          selectionChanged = true;

          if (fromCol > toCol) {
            fromCol = toCol;
          }
        }

        if (selectionChanged) {
          instance.selectCell(fromRow, fromCol, toRow, toCol);
        }
      }
      if (instance.view) {
        instance.view.wt.wtOverlays.adjustElementsSize();
      }
    },


    /**
     * Populate the data from the provided 2d array from the given cell coordinates.
     *
     * @private
     * @param {Object} start Start selection position. Visual indexes.
     * @param {Array} input 2d data array.
     * @param {Object} [end] End selection position (only for drag-down mode). Visual indexes.
     * @param {String} [source="populateFromArray"] Source information string.
     * @param {String} [method="overwrite"] Populate method. Possible options: `shift_down`, `shift_right`, `overwrite`.
     * @param {String} direction (left|right|up|down) String specifying the direction.
     * @param {Array} deltas The deltas array. A difference between values of adjacent cells.
     *                       Useful **only** when the type of handled cells is `numeric`.
     * @returns {Object|undefined} ending td in pasted area (only if any cell was changed).
     */
    populateFromArray: function populateFromArray(start, input, end, source, method, direction, deltas) {
      // TODO: either remove or implement the `direction` argument. Currently it's not working at all.
      var r,
          rlen,
          c,
          clen,
          setData = [],
          current = {};

      rlen = input.length;

      if (rlen === 0) {
        return false;
      }

      var repeatCol,
          repeatRow,
          cmax,
          rmax,
          baseEnd = {
        row: end === null ? null : end.row,
        col: end === null ? null : end.col
      };

      /* eslint-disable no-case-declarations */
      // insert data with specified pasteMode method
      switch (method) {
        case 'shift_down':
          repeatCol = end ? end.col - start.col + 1 : 0;
          repeatRow = end ? end.row - start.row + 1 : 0;
          input = (0, _data.translateRowsToColumns)(input);
          for (c = 0, clen = input.length, cmax = Math.max(clen, repeatCol); c < cmax; c++) {
            if (c < clen) {
              var _instance;

              for (r = 0, rlen = input[c].length; r < repeatRow - rlen; r++) {
                input[c].push(input[c][r % rlen]);
              }
              input[c].unshift(start.col + c, start.row, 0);
              (_instance = instance).spliceCol.apply(_instance, _toConsumableArray(input[c]));
            } else {
              var _instance2;

              input[c % clen][0] = start.col + c;
              (_instance2 = instance).spliceCol.apply(_instance2, _toConsumableArray(input[c % clen]));
            }
          }
          break;

        case 'shift_right':
          repeatCol = end ? end.col - start.col + 1 : 0;
          repeatRow = end ? end.row - start.row + 1 : 0;
          for (r = 0, rlen = input.length, rmax = Math.max(rlen, repeatRow); r < rmax; r++) {
            if (r < rlen) {
              var _instance3;

              for (c = 0, clen = input[r].length; c < repeatCol - clen; c++) {
                input[r].push(input[r][c % clen]);
              }
              input[r].unshift(start.row + r, start.col, 0);
              (_instance3 = instance).spliceRow.apply(_instance3, _toConsumableArray(input[r]));
            } else {
              var _instance4;

              input[r % rlen][0] = start.row + r;
              (_instance4 = instance).spliceRow.apply(_instance4, _toConsumableArray(input[r % rlen]));
            }
          }
          break;

        case 'overwrite':
        default:
          // overwrite and other not specified options
          current.row = start.row;
          current.col = start.col;

          var selected = { // selected range
            row: end && start ? end.row - start.row + 1 : 1,
            col: end && start ? end.col - start.col + 1 : 1
          };
          var skippedRow = 0;
          var skippedColumn = 0;
          var pushData = true;
          var cellMeta = void 0;

          var getInputValue = function getInputValue(row) {
            var col = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;

            var rowValue = input[row % input.length];

            if (col !== null) {
              return rowValue[col % rowValue.length];
            }

            return rowValue;
          };
          var rowInputLength = input.length;
          var rowSelectionLength = end ? end.row - start.row + 1 : 0;

          if (end) {
            rlen = rowSelectionLength;
          } else {
            rlen = Math.max(rowInputLength, rowSelectionLength);
          }
          for (r = 0; r < rlen; r++) {
            if (end && current.row > end.row && rowSelectionLength > rowInputLength || !priv.settings.allowInsertRow && current.row > instance.countRows() - 1 || current.row >= priv.settings.maxRows) {
              break;
            }
            var visualRow = r - skippedRow;
            var colInputLength = getInputValue(visualRow).length;
            var colSelectionLength = end ? end.col - start.col + 1 : 0;

            if (end) {
              clen = colSelectionLength;
            } else {
              clen = Math.max(colInputLength, colSelectionLength);
            }
            current.col = start.col;
            cellMeta = instance.getCellMeta(current.row, current.col);

            if ((source === 'CopyPaste.paste' || source === 'Autofill.autofill') && cellMeta.skipRowOnPaste) {
              skippedRow++;
              current.row++;
              rlen++;
              /* eslint-disable no-continue */
              continue;
            }
            skippedColumn = 0;

            for (c = 0; c < clen; c++) {
              if (end && current.col > end.col && colSelectionLength > colInputLength || !priv.settings.allowInsertColumn && current.col > instance.countCols() - 1 || current.col >= priv.settings.maxCols) {
                break;
              }
              cellMeta = instance.getCellMeta(current.row, current.col);

              if ((source === 'CopyPaste.paste' || source === 'Autofill.fill') && cellMeta.skipColumnOnPaste) {
                skippedColumn++;
                current.col++;
                clen++;
                continue;
              }
              if (cellMeta.readOnly) {
                current.col++;
                /* eslint-disable no-continue */
                continue;
              }
              var visualColumn = c - skippedColumn;
              var value = getInputValue(visualRow, visualColumn);
              var orgValue = instance.getDataAtCell(current.row, current.col);
              var index = {
                row: visualRow,
                col: visualColumn
              };

              if (source === 'Autofill.fill') {
                var result = instance.runHooks('beforeAutofillInsidePopulate', index, direction, input, deltas, {}, selected);

                if (result) {
                  value = (0, _mixed.isUndefined)(result.value) ? value : result.value;
                }
              }
              if (value !== null && (typeof value === 'undefined' ? 'undefined' : _typeof(value)) === 'object') {
                if (orgValue === null || (typeof orgValue === 'undefined' ? 'undefined' : _typeof(orgValue)) !== 'object') {
                  pushData = false;
                } else {
                  var orgValueSchema = (0, _object.duckSchema)(orgValue[0] || orgValue);
                  var valueSchema = (0, _object.duckSchema)(value[0] || value);

                  /* eslint-disable max-depth */
                  if ((0, _object.isObjectEquals)(orgValueSchema, valueSchema)) {
                    value = (0, _object.deepClone)(value);
                  } else {
                    pushData = false;
                  }
                }
              } else if (orgValue !== null && (typeof orgValue === 'undefined' ? 'undefined' : _typeof(orgValue)) === 'object') {
                pushData = false;
              }
              if (pushData) {
                setData.push([current.row, current.col, value]);
              }
              pushData = true;
              current.col++;
            }
            current.row++;
          }
          instance.setDataAtCell(setData, null, null, source || 'populateFromArray');
          break;
      }
    }
  };

  /* eslint-disable no-multi-assign */
  this.selection = selection = { // this public assignment is only temporary
    inProgress: false,

    selectedHeader: {
      cols: false,
      rows: false
    },

    /**
     * @param {Boolean} [rows=false]
     * @param {Boolean} [cols=false]
     * @param {Boolean} [corner=false]
     */
    setSelectedHeaders: function setSelectedHeaders() {
      var rows = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
      var cols = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
      var corner = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;

      instance.selection.selectedHeader.rows = rows;
      instance.selection.selectedHeader.cols = cols;
      instance.selection.selectedHeader.corner = corner;
    },


    /**
     * Sets inProgress to `true`. This enables onSelectionEnd and onSelectionEndByProp to function as desired.
     */
    begin: function begin() {
      instance.selection.inProgress = true;
    },


    /**
     * Sets inProgress to `false`. Triggers onSelectionEnd and onSelectionEndByProp.
     */
    finish: function finish() {
      var sel = instance.getSelected();
      instance.runHooks('afterSelectionEnd', sel[0], sel[1], sel[2], sel[3]);
      instance.runHooks('afterSelectionEndByProp', sel[0], instance.colToProp(sel[1]), sel[2], instance.colToProp(sel[3]));
      instance.selection.inProgress = false;
    },


    /**
     * @returns {Boolean}
     */
    isInProgress: function isInProgress() {
      return instance.selection.inProgress;
    },


    /**
     * Starts selection range on given td object.
     *
     * @param {CellCoords} coords Visual coords.
     * @param keepEditorOpened
     */
    setRangeStart: function setRangeStart(coords, keepEditorOpened) {
      instance.runHooks('beforeSetRangeStart', coords);
      priv.selRange = new _src.CellRange(coords, coords, coords);
      selection.setRangeEnd(coords, null, keepEditorOpened);
    },


    /**
     * Starts selection range on given td object.
     *
     * @param {CellCoords} coords Visual coords.
     * @param keepEditorOpened
     */
    setRangeStartOnly: function setRangeStartOnly(coords) {
      instance.runHooks('beforeSetRangeStartOnly', coords);
      priv.selRange = new _src.CellRange(coords, coords, coords);
    },


    /**
     * Ends selection range on given td object.
     *
     * @param {CellCoords} coords Visual coords.
     * @param {Boolean} [scrollToCell=true] If `true`, viewport will be scrolled to range end
     * @param {Boolean} [keepEditorOpened] If `true`, cell editor will be still opened after changing selection range
     */
    setRangeEnd: function setRangeEnd(coords, scrollToCell, keepEditorOpened) {
      if (priv.selRange === null) {
        return;
      }
      var disableVisualSelection,
          isHeaderSelected = false,
          areCoordsPositive = true;

      var firstVisibleRow = instance.view.wt.wtTable.getFirstVisibleRow();
      var firstVisibleColumn = instance.view.wt.wtTable.getFirstVisibleColumn();
      var newRangeCoords = {
        row: null,
        col: null
      };

      // trigger handlers
      instance.runHooks('beforeSetRangeEnd', coords);
      instance.selection.begin();

      newRangeCoords.row = coords.row < 0 ? firstVisibleRow : coords.row;
      newRangeCoords.col = coords.col < 0 ? firstVisibleColumn : coords.col;

      priv.selRange.to = new _src.CellCoords(newRangeCoords.row, newRangeCoords.col);

      if (!priv.settings.multiSelect) {
        priv.selRange.from = coords;
      }
      // set up current selection
      instance.view.wt.selections.current.clear();

      disableVisualSelection = instance.getCellMeta(priv.selRange.highlight.row, priv.selRange.highlight.col).disableVisualSelection;

      if (typeof disableVisualSelection === 'string') {
        disableVisualSelection = [disableVisualSelection];
      }

      if (disableVisualSelection === false || Array.isArray(disableVisualSelection) && disableVisualSelection.indexOf('current') === -1) {
        instance.view.wt.selections.current.add(priv.selRange.highlight);
      }
      // set up area selection
      instance.view.wt.selections.area.clear();

      if ((disableVisualSelection === false || Array.isArray(disableVisualSelection) && disableVisualSelection.indexOf('area') === -1) && selection.isMultiple()) {
        instance.view.wt.selections.area.add(priv.selRange.from);
        instance.view.wt.selections.area.add(priv.selRange.to);
      }
      // set up highlight
      if (priv.settings.currentHeaderClassName || priv.settings.currentRowClassName || priv.settings.currentColClassName) {
        instance.view.wt.selections.highlight.clear();
        instance.view.wt.selections.highlight.add(priv.selRange.from);
        instance.view.wt.selections.highlight.add(priv.selRange.to);
      }

      var preventScrolling = (0, _object.createObjectPropListener)('value');

      // trigger handlers
      instance.runHooks('afterSelection', priv.selRange.from.row, priv.selRange.from.col, priv.selRange.to.row, priv.selRange.to.col, preventScrolling);
      instance.runHooks('afterSelectionByProp', priv.selRange.from.row, datamap.colToProp(priv.selRange.from.col), priv.selRange.to.row, datamap.colToProp(priv.selRange.to.col), preventScrolling);

      if (priv.selRange.from.row === 0 && priv.selRange.to.row === instance.countRows() - 1 && instance.countRows() > 1 || priv.selRange.from.col === 0 && priv.selRange.to.col === instance.countCols() - 1 && instance.countCols() > 1) {
        isHeaderSelected = true;
      }

      if (coords.row < 0 || coords.col < 0) {
        areCoordsPositive = false;
      }

      if (preventScrolling.isTouched()) {
        scrollToCell = !preventScrolling.value;
      }

      if (scrollToCell !== false && !isHeaderSelected && areCoordsPositive) {
        if (priv.selRange.from && !selection.isMultiple()) {
          instance.view.scrollViewport(priv.selRange.from);
        } else {
          instance.view.scrollViewport(coords);
        }
      }

      if (selection.selectedHeader.rows && selection.selectedHeader.cols) {
        (0, _element.addClass)(instance.rootElement, ['ht__selection--rows', 'ht__selection--columns']);
      } else if (selection.selectedHeader.rows) {
        (0, _element.removeClass)(instance.rootElement, 'ht__selection--columns');
        (0, _element.addClass)(instance.rootElement, 'ht__selection--rows');
      } else if (selection.selectedHeader.cols) {
        (0, _element.removeClass)(instance.rootElement, 'ht__selection--rows');
        (0, _element.addClass)(instance.rootElement, 'ht__selection--columns');
      } else {
        (0, _element.removeClass)(instance.rootElement, ['ht__selection--rows', 'ht__selection--columns']);
      }

      selection.refreshBorders(null, keepEditorOpened);
    },


    /**
     * Destroys editor, redraws borders around cells, prepares editor.
     *
     * @param {Boolean} [revertOriginal]
     * @param {Boolean} [keepEditor]
     */
    refreshBorders: function refreshBorders(revertOriginal, keepEditor) {
      if (!keepEditor) {
        editorManager.destroyEditor(revertOriginal);
      }
      instance.view.render();

      if (selection.isSelected() && !keepEditor) {
        editorManager.prepareEditor();
      }
    },


    /**
     * Returns information if we have a multiselection.
     *
     * @returns {Boolean}
     */
    isMultiple: function isMultiple() {
      var isMultiple = !(priv.selRange.to.col === priv.selRange.from.col && priv.selRange.to.row === priv.selRange.from.row),
          modifier = instance.runHooks('afterIsMultipleSelection', isMultiple);

      if (isMultiple) {
        return modifier;
      }
    },


    /**
     * Selects cell relative to current cell (if possible).
     */
    transformStart: function transformStart(rowDelta, colDelta, force, keepEditorOpened) {
      var delta = new _src.CellCoords(rowDelta, colDelta),
          rowTransformDir = 0,
          colTransformDir = 0,
          totalRows,
          totalCols,
          coords,
          fixedRowsBottom;

      instance.runHooks('modifyTransformStart', delta);
      totalRows = instance.countRows();
      totalCols = instance.countCols();
      fixedRowsBottom = instance.getSettings().fixedRowsBottom;

      if (priv.selRange.highlight.row + rowDelta > totalRows - 1) {
        if (force && priv.settings.minSpareRows > 0 && !(fixedRowsBottom && priv.selRange.highlight.row >= totalRows - fixedRowsBottom - 1)) {
          instance.alter('insert_row', totalRows);
          totalRows = instance.countRows();
        } else if (priv.settings.autoWrapCol) {
          delta.row = 1 - totalRows;
          delta.col = priv.selRange.highlight.col + delta.col == totalCols - 1 ? 1 - totalCols : 1;
        }
      } else if (priv.settings.autoWrapCol && priv.selRange.highlight.row + delta.row < 0 && priv.selRange.highlight.col + delta.col >= 0) {
        delta.row = totalRows - 1;
        delta.col = priv.selRange.highlight.col + delta.col == 0 ? totalCols - 1 : -1;
      }

      if (priv.selRange.highlight.col + delta.col > totalCols - 1) {
        if (force && priv.settings.minSpareCols > 0) {
          instance.alter('insert_col', totalCols);
          totalCols = instance.countCols();
        } else if (priv.settings.autoWrapRow) {
          delta.row = priv.selRange.highlight.row + delta.row == totalRows - 1 ? 1 - totalRows : 1;
          delta.col = 1 - totalCols;
        }
      } else if (priv.settings.autoWrapRow && priv.selRange.highlight.col + delta.col < 0 && priv.selRange.highlight.row + delta.row >= 0) {
        delta.row = priv.selRange.highlight.row + delta.row == 0 ? totalRows - 1 : -1;
        delta.col = totalCols - 1;
      }

      coords = new _src.CellCoords(priv.selRange.highlight.row + delta.row, priv.selRange.highlight.col + delta.col);

      if (coords.row < 0) {
        rowTransformDir = -1;
        coords.row = 0;
      } else if (coords.row > 0 && coords.row >= totalRows) {
        rowTransformDir = 1;
        coords.row = totalRows - 1;
      }

      if (coords.col < 0) {
        colTransformDir = -1;
        coords.col = 0;
      } else if (coords.col > 0 && coords.col >= totalCols) {
        colTransformDir = 1;
        coords.col = totalCols - 1;
      }
      instance.runHooks('afterModifyTransformStart', coords, rowTransformDir, colTransformDir);
      selection.setRangeStart(coords, keepEditorOpened);
    },


    /**
     * Sets selection end cell relative to current selection end cell (if possible).
     */
    transformEnd: function transformEnd(rowDelta, colDelta) {
      var delta = new _src.CellCoords(rowDelta, colDelta),
          rowTransformDir = 0,
          colTransformDir = 0,
          totalRows,
          totalCols,
          coords;

      instance.runHooks('modifyTransformEnd', delta);

      totalRows = instance.countRows();
      totalCols = instance.countCols();
      coords = new _src.CellCoords(priv.selRange.to.row + delta.row, priv.selRange.to.col + delta.col);

      if (coords.row < 0) {
        rowTransformDir = -1;
        coords.row = 0;
      } else if (coords.row > 0 && coords.row >= totalRows) {
        rowTransformDir = 1;
        coords.row = totalRows - 1;
      }

      if (coords.col < 0) {
        colTransformDir = -1;
        coords.col = 0;
      } else if (coords.col > 0 && coords.col >= totalCols) {
        colTransformDir = 1;
        coords.col = totalCols - 1;
      }
      instance.runHooks('afterModifyTransformEnd', coords, rowTransformDir, colTransformDir);
      selection.setRangeEnd(coords, true);
    },


    /**
     * Returns `true` if currently there is a selection on screen, `false` otherwise.
     *
     * @returns {Boolean}
     */
    isSelected: function isSelected() {
      return priv.selRange !== null;
    },


    /**
     * Returns `true` if coords is within current selection coords.
     *
     * @param {CellCoords} coords
     * @returns {Boolean}
     */
    inInSelection: function inInSelection(coords) {
      if (!selection.isSelected()) {
        return false;
      }

      return priv.selRange.includes(coords);
    },


    /**
     * Deselects all selected cells
     */
    deselect: function deselect() {
      if (!selection.isSelected()) {
        return;
      }
      instance.selection.inProgress = false; // needed by HT inception
      priv.selRange = null;
      instance.view.wt.selections.current.clear();
      instance.view.wt.selections.area.clear();
      if (priv.settings.currentHeaderClassName || priv.settings.currentRowClassName || priv.settings.currentColClassName) {
        instance.view.wt.selections.highlight.clear();
      }
      editorManager.destroyEditor();
      selection.refreshBorders();
      (0, _element.removeClass)(instance.rootElement, ['ht__selection--rows', 'ht__selection--columns']);
      instance.runHooks('afterDeselect');
    },


    /**
     * Select all cells
     */
    selectAll: function selectAll() {
      if (!priv.settings.multiSelect) {
        return;
      }
      selection.setSelectedHeaders(true, true, true);
      selection.setRangeStart(new _src.CellCoords(0, 0));
      selection.setRangeEnd(new _src.CellCoords(instance.countRows() - 1, instance.countCols() - 1), false);
    },


    /**
     * Deletes data from selected cells
     */
    empty: function empty() {
      if (!selection.isSelected()) {
        return;
      }
      var topLeft = priv.selRange.getTopLeftCorner();
      var bottomRight = priv.selRange.getBottomRightCorner();
      var r,
          c,
          changes = [];

      for (r = topLeft.row; r <= bottomRight.row; r++) {
        for (c = topLeft.col; c <= bottomRight.col; c++) {
          if (!instance.getCellMeta(r, c).readOnly) {
            changes.push([r, c, '']);
          }
        }
      }
      instance.setDataAtCell(changes);
    }
  };

  this.init = function () {
    dataSource.setData(priv.settings.data);
    instance.runHooks('beforeInit');

    if ((0, _browser.isMobileBrowser)()) {
      (0, _element.addClass)(instance.rootElement, 'mobile');
    }

    this.updateSettings(priv.settings, true);

    this.view = new _tableView2.default(this);
    editorManager = new _editorManager2.default(instance, priv, selection, datamap);

    this.forceFullRender = true; // used when data was changed

    instance.runHooks('init');
    this.view.render();

    if (_typeof(priv.firstRun) === 'object') {
      instance.runHooks('afterChange', priv.firstRun[0], priv.firstRun[1]);
      priv.firstRun = false;
    }
    instance.runHooks('afterInit');
  };

  function ValidatorsQueue() {
    // moved this one level up so it can be used in any function here. Probably this should be moved to a separate file
    var resolved = false;

    return {
      validatorsInQueue: 0,
      valid: true,
      addValidatorToQueue: function addValidatorToQueue() {
        this.validatorsInQueue++;
        resolved = false;
      },
      removeValidatorFormQueue: function removeValidatorFormQueue() {
        this.validatorsInQueue = this.validatorsInQueue - 1 < 0 ? 0 : this.validatorsInQueue - 1;
        this.checkIfQueueIsEmpty();
      },
      onQueueEmpty: function onQueueEmpty(valid) {},
      checkIfQueueIsEmpty: function checkIfQueueIsEmpty() {
        if (this.validatorsInQueue == 0 && resolved == false) {
          resolved = true;
          this.onQueueEmpty(this.valid);
        }
      }
    };
  }

  function validateChanges(changes, source, callback) {
    var waitingForValidator = new ValidatorsQueue();
    waitingForValidator.onQueueEmpty = resolve;

    for (var i = changes.length - 1; i >= 0; i--) {
      if (changes[i] === null) {
        changes.splice(i, 1);
      } else {
        var row = changes[i][0];
        var col = datamap.propToCol(changes[i][1]);

        var cellProperties = instance.getCellMeta(row, col);

        if (cellProperties.type === 'numeric' && typeof changes[i][3] === 'string') {
          if (changes[i][3].length > 0 && (/^-?[\d\s]*(\.|,)?\d*$/.test(changes[i][3]) || cellProperties.format)) {
            var len = changes[i][3].length;

            if ((0, _mixed.isUndefined)(cellProperties.language)) {
              _numbro2.default.culture('en-US');
            } else if (changes[i][3].indexOf('.') === len - 3 && changes[i][3].indexOf(',') === -1) {
              // this input in format XXXX.XX is likely to come from paste. Let's parse it using international rules
              _numbro2.default.culture('en-US');
            } else {

              _numbro2.default.culture(cellProperties.language);
            }

            var _numbro$cultureData = _numbro2.default.cultureData(_numbro2.default.culture()),
                delimiters = _numbro$cultureData.delimiters;

            // try to parse to float - https://github.com/foretagsplatsen/numbro/pull/183


            if (_numbro2.default.validate(changes[i][3]) && !isNaN(changes[i][3])) {
              changes[i][3] = parseFloat(changes[i][3]);
            } else {
              changes[i][3] = (0, _numbro2.default)().unformat(changes[i][3]) || changes[i][3];
            }
          }
        }

        /* eslint-disable no-loop-func */
        if (instance.getCellValidator(cellProperties)) {
          waitingForValidator.addValidatorToQueue();
          instance.validateCell(changes[i][3], cellProperties, function (i, cellProperties) {
            return function (result) {
              if (typeof result !== 'boolean') {
                throw new Error('Validation error: result is not boolean');
              }
              if (result === false && cellProperties.allowInvalid === false) {
                changes.splice(i, 1); // cancel the change
                cellProperties.valid = true; // we cancelled the change, so cell value is still valid
                var cell = instance.getCell(cellProperties.row, cellProperties.col);
                (0, _element.removeClass)(cell, instance.getSettings().invalidCellClassName);
                --i;
              }
              waitingForValidator.removeValidatorFormQueue();
            };
          }(i, cellProperties), source);
        }
      }
    }
    waitingForValidator.checkIfQueueIsEmpty();

    function resolve() {
      var beforeChangeResult;

      if (changes.length) {
        beforeChangeResult = instance.runHooks('beforeChange', changes, source);
        if ((0, _function.isFunction)(beforeChangeResult)) {
          console.warn('Your beforeChange callback returns a function. It\'s not supported since Handsontable 0.12.1 (and the returned function will not be executed).');
        } else if (beforeChangeResult === false) {
          changes.splice(0, changes.length); // invalidate all changes (remove everything from array)
        }
      }
      callback(); // called when async validators are resolved and beforeChange was not async
    }
  }

  /**
   * Internal function to apply changes. Called after validateChanges
   *
   * @private
   * @param {Array} changes Array in form of [row, prop, oldValue, newValue]
   * @param {String} source String that identifies how this change will be described in changes array (useful in onChange callback)
   * @fires Hooks#beforeChangeRender
   * @fires Hooks#afterChange
   */
  function applyChanges(changes, source) {
    var i = changes.length - 1;

    if (i < 0) {
      return;
    }

    for (; i >= 0; i--) {
      var skipThisChange = false;

      if (changes[i] === null) {
        changes.splice(i, 1);
        /* eslint-disable no-continue */
        continue;
      }

      if (changes[i][2] == null && changes[i][3] == null) {
        /* eslint-disable no-continue */
        continue;
      }

      if (priv.settings.allowInsertRow) {
        while (changes[i][0] > instance.countRows() - 1) {
          var numberOfCreatedRows = datamap.createRow(void 0, void 0, source);

          if (numberOfCreatedRows === 0) {
            skipThisChange = true;
            break;
          }
        }
      }

      if (skipThisChange) {
        /* eslint-disable no-continue */
        continue;
      }

      if (instance.dataType === 'array' && (!priv.settings.columns || priv.settings.columns.length === 0) && priv.settings.allowInsertColumn) {
        while (datamap.propToCol(changes[i][1]) > instance.countCols() - 1) {
          datamap.createCol(void 0, void 0, source);
        }
      }

      datamap.set(changes[i][0], changes[i][1], changes[i][3]);
    }

    instance.forceFullRender = true; // used when data was changed
    grid.adjustRowsAndCols();
    instance.runHooks('beforeChangeRender', changes, source);
    selection.refreshBorders(null, true);
    instance.view.wt.wtOverlays.adjustElementsSize();
    instance.runHooks('afterChange', changes, source || 'edit');

    var activeEditor = instance.getActiveEditor();

    if (activeEditor && (0, _mixed.isDefined)(activeEditor.refreshValue)) {
      activeEditor.refreshValue();
    }
  }

  this.validateCell = function (value, cellProperties, callback, source) {
    var validator = instance.getCellValidator(cellProperties);

    function done(valid) {
      var col = cellProperties.visualCol,
          row = cellProperties.visualRow,
          td = instance.getCell(row, col, true);

      if (td && td.nodeName != 'TH') {
        instance.view.wt.wtSettings.settings.cellRenderer(row, col, td);
      }
      callback(valid);
    }

    if ((0, _mixed.isRegExp)(validator)) {
      validator = function (validator) {
        return function (value, callback) {
          callback(validator.test(value));
        };
      }(validator);
    }

    if ((0, _function.isFunction)(validator)) {

      value = instance.runHooks('beforeValidate', value, cellProperties.visualRow, cellProperties.prop, source);

      // To provide consistent behaviour, validation should be always asynchronous
      instance._registerTimeout(setTimeout(function () {
        validator.call(cellProperties, value, function (valid) {
          valid = instance.runHooks('afterValidate', valid, value, cellProperties.visualRow, cellProperties.prop, source);
          cellProperties.valid = valid;

          done(valid);
          instance.runHooks('postAfterValidate', valid, value, cellProperties.visualRow, cellProperties.prop, source);
        });
      }, 0));
    } else {
      // resolve callback even if validator function was not found
      instance._registerTimeout(setTimeout(function () {
        cellProperties.valid = true;
        done(cellProperties.valid);
      }, 0));
    }
  };

  function setDataInputToArray(row, propOrCol, value) {
    if ((typeof row === 'undefined' ? 'undefined' : _typeof(row)) === 'object') {
      // is it an array of changes
      return row;
    }
    return [[row, propOrCol, value]];
  }

  /**
   * @description
   * Set new value to a cell. To change many cells at once, pass an array of `changes` in format `[[row, col, value], ...]` as
   * the only parameter. `col` is the index of a __visible__ column (note that if columns were reordered,
   * the current visible order will be used). `source` is a flag for before/afterChange events. If you pass only array of
   * changes then `source` could be set as second parameter.
   *
   * @memberof Core#
   * @function setDataAtCell
   * @param {Number|Array} row Visual row index or array of changes in format `[[row, col, value], ...]`.
   * @param {Number} col Visual column index.
   * @param {String} value New value.
   * @param {String} [source] String that identifies how this change will be described in the changes array (useful in onAfterChange or onBeforeChange callback).
   */
  this.setDataAtCell = function (row, col, value, source) {
    var input = setDataInputToArray(row, col, value),
        i,
        ilen,
        changes = [],
        prop;

    for (i = 0, ilen = input.length; i < ilen; i++) {
      if (_typeof(input[i]) !== 'object') {
        throw new Error('Method `setDataAtCell` accepts row number or changes array of arrays as its first parameter');
      }
      if (typeof input[i][1] !== 'number') {
        throw new Error('Method `setDataAtCell` accepts row and column number as its parameters. If you want to use object property name, use method `setDataAtRowProp`');
      }
      prop = datamap.colToProp(input[i][1]);
      changes.push([input[i][0], prop, dataSource.getAtCell(recordTranslator.toPhysicalRow(input[i][0]), input[i][1]), input[i][2]]);
    }

    if (!source && (typeof row === 'undefined' ? 'undefined' : _typeof(row)) === 'object') {
      source = col;
    }

    instance.runHooks('afterSetDataAtCell', changes, source);

    validateChanges(changes, source, function () {
      applyChanges(changes, source);
    });
  };

  /**
   * @description
   * Set new value to a cell. To change many cells at once, pass an array of `changes` in format `[[row, prop, value], ...]` as
   * the only parameter. `prop` is the name of the object property (e.g. `first.name`). `source` is a flag for before/afterChange events.
   * If you pass only array of changes then `source` could be set as second parameter.
   *
   * @memberof Core#
   * @function setDataAtRowProp
   * @param {Number|Array} row Visual row index or array of changes in format `[[row, prop, value], ...]`.
   * @param {String} prop Property name or the source string.
   * @param {String} value Value to be set.
   * @param {String} [source] String that identifies how this change will be described in changes array (useful in onChange callback).
   */
  this.setDataAtRowProp = function (row, prop, value, source) {
    var input = setDataInputToArray(row, prop, value),
        i,
        ilen,
        changes = [];

    for (i = 0, ilen = input.length; i < ilen; i++) {
      changes.push([input[i][0], input[i][1], dataSource.getAtCell(recordTranslator.toPhysicalRow(input[i][0]), input[i][1]), input[i][2]]);
    }

    if (!source && (typeof row === 'undefined' ? 'undefined' : _typeof(row)) === 'object') {
      source = prop;
    }

    instance.runHooks('afterSetDataAtRowProp', changes, source);

    validateChanges(changes, source, function () {
      applyChanges(changes, source);
    });
  };

  /**
   * Listen to the keyboard input on document body.
   *
   * @memberof Core#
   * @function listen
   * @since 0.11
   */
  this.listen = function () {
    var invalidActiveElement = !document.activeElement || document.activeElement && document.activeElement.nodeName === void 0;

    if (document.activeElement && document.activeElement !== document.body && !invalidActiveElement) {
      document.activeElement.blur();
    } else if (invalidActiveElement) {
      // IE
      document.body.focus();
    }

    activeGuid = instance.guid;
  };

  /**
   * Stop listening to keyboard input on the document body.
   *
   * @memberof Core#
   * @function unlisten
   * @since 0.11
   */
  this.unlisten = function () {
    if (this.isListening()) {
      activeGuid = null;
    }
  };

  /**
   * Returns `true` if the current Handsontable instance is listening to keyboard input on document body.
   *
   * @memberof Core#
   * @function isListening
   * @since 0.11
   * @returns {Boolean} `true` if the instance is listening, `false` otherwise.
   */
  this.isListening = function () {
    return activeGuid === instance.guid;
  };

  /**
   * Destroys the current editor, renders and selects the current cell.
   *
   * @memberof Core#
   * @function destroyEditor
   * @param {Boolean} [revertOriginal] If != `true`, edited data is saved. Otherwise the previous value is restored.
   */
  this.destroyEditor = function (revertOriginal) {
    selection.refreshBorders(revertOriginal);
  };

  /**
   * Populate cells at position with 2D input array (e.g. `[[1, 2], [3, 4]]`).
   * Use `endRow`, `endCol` when you want to cut input when a certain row is reached.
   * Optional `source` parameter (default value "populateFromArray") is used to identify this call in the resulting events (beforeChange, afterChange).
   * Optional `populateMethod` parameter (default value "overwrite", possible values "shift_down" and "shift_right")
   * has the same effect as pasteMode option {@link Options#pasteMode}
   *
   * @memberof Core#
   * @function populateFromArray
   * @since 0.9.0
   * @param {Number} row Start visual row index.
   * @param {Number} col Start visual column index.
   * @param {Array} input 2d array
   * @param {Number} [endRow] End visual row index (use when you want to cut input when certain row is reached).
   * @param {Number} [endCol] End visual column index (use when you want to cut input when certain column is reached).
   * @param {String} [source="populateFromArray"] Source string.
   * @param {String} [method="overwrite"] Populate method. Possible options: `shift_down`, `shift_right`, `overwrite`.
   * @param {String} direction Populate direction. (left|right|up|down)
   * @param {Array} deltas Deltas array.
   * @returns {Object|undefined} The ending TD element in pasted area (only if any cells were changed).
   */
  this.populateFromArray = function (row, col, input, endRow, endCol, source, method, direction, deltas) {
    var c;

    if (!((typeof input === 'undefined' ? 'undefined' : _typeof(input)) === 'object' && _typeof(input[0]) === 'object')) {
      throw new Error('populateFromArray parameter `input` must be an array of arrays'); // API changed in 0.9-beta2, let's check if you use it correctly
    }
    c = typeof endRow === 'number' ? new _src.CellCoords(endRow, endCol) : null;

    return grid.populateFromArray(new _src.CellCoords(row, col), input, c, source, method, direction, deltas);
  };

  /**
   * Adds/removes data from the column. This function is modelled after Array.splice.
   * Parameter `col` is the index of the column in which do you want to do splice.
   * Parameter `index` is the row index at which to start changing the array.
   * If negative, will begin that many elements from the end. Parameter `amount`, is the number of the old array elements to remove.
   * If the amount is 0, no elements are removed. Fourth and further parameters are the `elements` to add to the array.
   * If you don't specify any elements, spliceCol simply removes elements from the array.
   * {@link DataMap#spliceCol}
   *
   * @memberof Core#
   * @function spliceCol
   * @since 0.9-beta2
   * @param {Number} col Index of the column in which do you want to do splice.
   * @param {Number} index Index at which to start changing the array. If negative, will begin that many elements from the end.
   * @param {Number} amount An integer indicating the number of old array elements to remove. If amount is 0, no elements are removed.
   * @param {*} [elements] The elements to add to the array. If you don't specify any elements, spliceCol simply removes elements from the array.
   */
  this.spliceCol = function (col, index, amount /* , elements... */) {
    var _datamap;

    return (_datamap = datamap).spliceCol.apply(_datamap, arguments);
  };

  /**
   * Adds/removes data from the row. This function works is modelled after Array.splice.
   * Parameter `row` is the index of row in which do you want to do splice.
   * Parameter `index` is the column index at which to start changing the array.
   * If negative, will begin that many elements from the end. Parameter `amount`, is the number of old array elements to remove.
   * If the amount is 0, no elements are removed. Fourth and further parameters are the `elements` to add to the array.
   * If you don't specify any elements, spliceCol simply removes elements from the array.
   * {@link DataMap#spliceRow}
   *
   * @memberof Core#
   * @function spliceRow
   * @since 0.11
   * @param {Number} row Index of column in which do you want to do splice.
   * @param {Number} index Index at which to start changing the array. If negative, will begin that many elements from the end.
   * @param {Number} amount An integer indicating the number of old array elements to remove. If amount is 0, no elements are removed.
   * @param {*} [elements] The elements to add to the array. If you don't specify any elements, spliceCol simply removes elements from the array.
   */
  this.spliceRow = function (row, index, amount /* , elements... */) {
    var _datamap2;

    return (_datamap2 = datamap).spliceRow.apply(_datamap2, arguments);
  };

  /**
   * Returns indexes of the currently selected cells as an array `[startRow, startCol, endRow, endCol]`.
   *
   * Start row and start col are the coordinates of the active cell (where the selection was started).
   *
   * @memberof Core#
   * @function getSelected
   * @returns {Array} Array of the selection's indexes.
   */
  this.getSelected = function () {
    // https://github.com/handsontable/handsontable/issues/44  //cjl
    if (selection.isSelected()) {
      return [priv.selRange.from.row, priv.selRange.from.col, priv.selRange.to.row, priv.selRange.to.col];
    }
  };

  /**
   * Returns the current selection as a CellRange object.
   *
   * @memberof Core#
   * @function getSelectedRange
   * @since 0.11
   * @returns {CellRange} Selected range object or undefined` if there is no selection.
   */
  this.getSelectedRange = function () {
    // https://github.com/handsontable/handsontable/issues/44  //cjl
    if (selection.isSelected()) {
      return priv.selRange;
    }
  };

  /**
   * Rerender the table.
   *
   * @memberof Core#
   * @function render
   */
  this.render = function () {
    if (instance.view) {
      instance.renderCall = true;
      instance.forceFullRender = true; // used when data was changed
      selection.refreshBorders(null, true);
    }
  };

  /**
   * Reset all cells in the grid to contain data from the data array.
   *
   * @memberof Core#
   * @function loadData
   * @param {Array} data Array of arrays or array of objects containing data.
   * @fires Hooks#afterLoadData
   * @fires Hooks#afterChange
   */
  this.loadData = function (data) {
    if (Array.isArray(priv.settings.dataSchema)) {
      instance.dataType = 'array';
    } else if ((0, _function.isFunction)(priv.settings.dataSchema)) {
      instance.dataType = 'function';
    } else {
      instance.dataType = 'object';
    }

    if (datamap) {
      datamap.destroy();
    }
    datamap = new _dataMap2.default(instance, priv, GridSettings);

    if ((typeof data === 'undefined' ? 'undefined' : _typeof(data)) === 'object' && data !== null) {
      if (!(data.push && data.splice)) {
        // check if data is array. Must use duck-type check so Backbone Collections also pass it
        // when data is not an array, attempt to make a single-row array of it
        data = [data];
      }
    } else if (data === null) {
      data = [];
      var row;
      var r = 0;
      var rlen = 0;
      var dataSchema = datamap.getSchema();

      for (r = 0, rlen = priv.settings.startRows; r < rlen; r++) {
        if ((instance.dataType === 'object' || instance.dataType === 'function') && priv.settings.dataSchema) {
          row = (0, _object.deepClone)(dataSchema);
          data.push(row);
        } else if (instance.dataType === 'array') {
          row = (0, _object.deepClone)(dataSchema[0]);
          data.push(row);
        } else {
          row = [];

          for (var c = 0, clen = priv.settings.startCols; c < clen; c++) {
            row.push(null);
          }

          data.push(row);
        }
      }
    } else {
      throw new Error('loadData only accepts array of objects or array of arrays (' + (typeof data === 'undefined' ? 'undefined' : _typeof(data)) + ' given)');
    }

    priv.isPopulated = false;
    GridSettings.prototype.data = data;

    if (Array.isArray(data[0])) {
      instance.dataType = 'array';
    }

    datamap.dataSource = data;
    dataSource.data = data;
    dataSource.dataType = instance.dataType;
    dataSource.colToProp = datamap.colToProp.bind(datamap);
    dataSource.propToCol = datamap.propToCol.bind(datamap);

    clearCellSettingCache();

    grid.adjustRowsAndCols();
    instance.runHooks('afterLoadData', priv.firstRun);

    if (priv.firstRun) {
      priv.firstRun = [null, 'loadData'];
    } else {
      instance.runHooks('afterChange', null, 'loadData');
      instance.render();
    }
    priv.isPopulated = true;

    function clearCellSettingCache() {
      priv.cellSettings.length = 0;
    }
  };

  /**
   * Returns the current data object (the same one that was passed by `data` configuration option or `loadData` method,
   * unless the `modifyRow` hook was used to trim some of the rows. If that's the case - use the {@link Core#getSourceData} method.).
   * Optionally you can provide cell range by defining `row`, `col`, `row2`, `col2` to get only a fragment of grid data.
   *
   * Note: getData functionality changed with the release of version 0.20. If you're looking for the previous functionality,
   * you should use the {@link Core#getSourceData} method.
   *
   * @memberof Core#
   * @function getData
   * @param {Number} [r] From visual row index.
   * @param {Number} [c] From visual column index.
   * @param {Number} [r2] To visual row index.
   * @param {Number} [c2] To visual column index.
   * @returns {Array} Array with the data.
   */
  this.getData = function (r, c, r2, c2) {
    if ((0, _mixed.isUndefined)(r)) {
      return datamap.getAll();
    }
    return datamap.getRange(new _src.CellCoords(r, c), new _src.CellCoords(r2, c2), datamap.DESTINATION_RENDERER);
  };

  /**
   * Returns a string value of the selected range. Each column is separated by tab, each row is separated by a new line character.
   * {@link DataMap#getCopyableText}
   *
   * @memberof Core#
   * @function getCopyableText
   * @since 0.11
   * @param {Number} startRow From visual row index.
   * @param {Number} startCol From visual column index.
   * @param {Number} endRow To visual row index.
   * @param {Number} endCol To visual column index.
   * @returns {String}
   */
  this.getCopyableText = function (startRow, startCol, endRow, endCol) {
    return datamap.getCopyableText(new _src.CellCoords(startRow, startCol), new _src.CellCoords(endRow, endCol));
  };

  /**
   * Returns the data's copyable value at specified row and column index ({@link DataMap#getCopyable}).
   *
   * @memberof Core#
   * @function getCopyableData
   * @since 0.19.0
   * @param {Number} row Visual row index.
   * @param {Number} column Visual column index.
   * @returns {String}
   */
  this.getCopyableData = function (row, column) {
    return datamap.getCopyable(row, datamap.colToProp(column));
  };

  /**
   * Returns schema provided by constructor settings. If it doesn't exist then it returns the schema based on the data
   * structure in the first row.
   *
   * @memberof Core#
   * @function getSchema
   * @since 0.13.2
   * @returns {Object} Schema object.
   */
  this.getSchema = function () {
    return datamap.getSchema();
  };

  /**
   * Use it if you need to change configuration after initialization. The `settings` parameter is an object containing the new
   * settings, declared the same way as in the initial settings object.
   * Note, that although the `updateSettings` method doesn't overwrite the previously declared settings, it might reset
   * the settings made post-initialization. (for example - ignore changes made using the columnResize feature).
   *
   * @memberof Core#
   * @function updateSettings
   * @param {Object} settings New settings object.
   * @param {Boolean} init Calls this method in the initialization mode. Internal use only.
   *                       Used by API could be cause of the unexpected behaviour of the Handsontable.
   * @example
   * ```js
   * hot.updateSettings({
   *    contextMenu: true,
   *    colHeaders: true,
   *    fixedRowsTop: 2
   * });
   * ```
   * @fires Hooks#afterCellMetaReset
   * @fires Hooks#afterUpdateSettings
   */
  this.updateSettings = function (settings, init) {
    var columnsAsFunc = false;
    var i = void 0;
    var j = void 0;
    var clen = void 0;

    if ((0, _mixed.isDefined)(settings.rows)) {
      throw new Error('"rows" setting is no longer supported. do you mean startRows, minRows or maxRows?');
    }
    if ((0, _mixed.isDefined)(settings.cols)) {
      throw new Error('"cols" setting is no longer supported. do you mean startCols, minCols or maxCols?');
    }

    for (i in settings) {
      if (i === 'data') {
        /* eslint-disable no-continue */
        continue; // loadData will be triggered later
      } else if (_pluginHooks2.default.getSingleton().getRegistered().indexOf(i) > -1) {
        if ((0, _function.isFunction)(settings[i]) || Array.isArray(settings[i])) {
          settings[i].initialHook = true;
          instance.addHook(i, settings[i]);
        }
      } else if (!init && (0, _object.hasOwnProperty)(settings, i)) {
        // Update settings
        GridSettings.prototype[i] = settings[i];
      }
    }

    // Load data or create data map
    if (settings.data === void 0 && priv.settings.data === void 0) {
      instance.loadData(null); // data source created just now
    } else if (settings.data !== void 0) {
      instance.loadData(settings.data); // data source given as option
    } else if (settings.columns !== void 0) {
      datamap.createMap();
    }

    clen = instance.countCols();

    var columnSetting = settings.columns || GridSettings.prototype.columns;

    // Init columns constructors configuration
    if (columnSetting && (0, _function.isFunction)(columnSetting)) {
      clen = instance.countSourceCols();
      columnsAsFunc = true;
    }

    // Clear cellSettings cache
    if (settings.cell !== void 0 || settings.cells !== void 0 || settings.columns !== void 0) {
      priv.cellSettings.length = 0;
    }

    if (clen > 0) {
      var proto = void 0;
      var column = void 0;

      for (i = 0, j = 0; i < clen; i++) {
        if (columnsAsFunc && !columnSetting(i)) {
          /* eslint-disable no-continue */
          continue;
        }
        priv.columnSettings[j] = (0, _setting.columnFactory)(GridSettings, priv.columnsSettingConflicts);

        // shortcut for prototype
        proto = priv.columnSettings[j].prototype;

        // Use settings provided by user
        if (columnSetting) {
          if (columnsAsFunc) {
            column = columnSetting(i);
          } else {
            column = columnSetting[j];
          }

          if (column) {
            (0, _object.extend)(proto, column);
            (0, _object.extend)(proto, expandType(column));
          }
        }

        j++;
      }
    }

    if ((0, _mixed.isDefined)(settings.cell)) {
      for (var key in settings.cell) {
        if ((0, _object.hasOwnProperty)(settings.cell, key)) {
          var cell = settings.cell[key];

          instance.setCellMetaObject(cell.row, cell.col, cell);
        }
      }
    }

    instance.runHooks('afterCellMetaReset');

    if ((0, _mixed.isDefined)(settings.className)) {
      if (GridSettings.prototype.className) {
        (0, _element.removeClass)(instance.rootElement, GridSettings.prototype.className);
      }
      if (settings.className) {
        (0, _element.addClass)(instance.rootElement, settings.className);
      }
    }

    var currentHeight = instance.rootElement.style.height;
    if (currentHeight !== '') {
      currentHeight = parseInt(instance.rootElement.style.height, 10);
    }

    var height = settings.height;
    if ((0, _function.isFunction)(height)) {
      height = height();
    }

    if (init) {
      var initialStyle = instance.rootElement.getAttribute('style');

      if (initialStyle) {
        instance.rootElement.setAttribute('data-initialstyle', instance.rootElement.getAttribute('style'));
      }
    }

    if (height === null) {
      var _initialStyle = instance.rootElement.getAttribute('data-initialstyle');

      if (_initialStyle && (_initialStyle.indexOf('height') > -1 || _initialStyle.indexOf('overflow') > -1)) {
        instance.rootElement.setAttribute('style', _initialStyle);
      } else {
        instance.rootElement.style.height = '';
        instance.rootElement.style.overflow = '';
      }
    } else if (height !== void 0) {
      instance.rootElement.style.height = height + 'px';
      instance.rootElement.style.overflow = 'hidden';
    }

    if (typeof settings.width !== 'undefined') {
      var width = settings.width;

      if ((0, _function.isFunction)(width)) {
        width = width();
      }

      instance.rootElement.style.width = width + 'px';
    }

    if (!init) {
      datamap.clearLengthCache(); // force clear cache length on updateSettings() #3416

      if (instance.view) {
        instance.view.wt.wtViewport.resetHasOversizedColumnHeadersMarked();
      }

      instance.runHooks('afterUpdateSettings', settings);
    }

    grid.adjustRowsAndCols();
    if (instance.view && !priv.firstRun) {
      instance.forceFullRender = true; // used when data was changed
      selection.refreshBorders(null, true);
    }

    if (!init && instance.view && (currentHeight === '' || height === '' || height === void 0) && currentHeight !== height) {
      instance.view.wt.wtOverlays.updateMainScrollableElements();
    }
  };

  /**
   * Get value from the selected cell.
   *
   * @memberof Core#
   * @function getValue
   * @since 0.11
   * @returns {*} Value of selected cell.
   */
  this.getValue = function () {
    var sel = instance.getSelected();
    if (GridSettings.prototype.getValue) {
      if ((0, _function.isFunction)(GridSettings.prototype.getValue)) {
        return GridSettings.prototype.getValue.call(instance);
      } else if (sel) {
        return instance.getData()[sel[0]][GridSettings.prototype.getValue];
      }
    } else if (sel) {
      return instance.getDataAtCell(sel[0], sel[1]);
    }
  };

  function expandType(obj) {
    if (!(0, _object.hasOwnProperty)(obj, 'type')) {
      // ignore obj.prototype.type
      return;
    }

    var type,
        expandedType = {};

    if (_typeof(obj.type) === 'object') {
      type = obj.type;
    } else if (typeof obj.type === 'string') {
      type = (0, _cellTypes.getCellType)(obj.type);
    }

    for (var i in type) {
      if ((0, _object.hasOwnProperty)(type, i) && !(0, _object.hasOwnProperty)(obj, i)) {
        expandedType[i] = type[i];
      }
    }

    return expandedType;
  }

  /**
   * Returns the object settings.
   *
   * @memberof Core#
   * @function getSettings
   * @returns {Object} Object containing the current grid settings.
   */
  this.getSettings = function () {
    return priv.settings;
  };

  /**
   * Clears the data from the grid. (The table settings remain intact.)
   *
   * @memberof Core#
   * @function clear
   * @since 0.11
   */
  this.clear = function () {
    selection.selectAll();
    selection.empty();
  };

  /**
   * @memberof Core#
   * @function alter
   * @param {String} action See grid.alter for possible values: `"insert_row"`, `"insert_col"`, `"remove_row"`, `"remove_col"`
   * @param {Number} index Visual index of the row/column before which the new row/column will be inserted/removed.
   * @param {Number} [amount = 1] Amound of rows/columns to be inserted/removed.
   * @param {String} [source] Source indicator.
   * @param {Boolean} [keepEmptyRows] Flag for preventing deletion of empty rows.
   * @description
   *
   * Allows altering the table structure by either inserting/removing rows or inserting/removing columns:
   *
   * Insert new row(s) above the row with a given `index`. If index is `null` or `undefined`, the new row will be
   * added after the last row.
   * ```js
   * var hot = new Handsontable(document.getElementById('example'));
   * hot.alter('insert_row', 10);
   * ```
   *
   * Insert new column(s) before the column with a given `index`. If index is `null` or `undefined`, the new column
   * will be added after the last column.
   * ```js
   * var hot = new Handsontable(document.getElementById('example'));
   * hot.alter('insert_col', 10);
   * ```
   *
   * Remove the row(s) at the given `index`.
   * ```js
   * var hot = new Handsontable(document.getElementById('example'));
   * hot.alter('remove_row', 10);
   * ```
   *
   * Remove the column(s) at the given `index`.
   * ```js
   * var hot = new Handsontable(document.getElementById('example'));
   * hot.alter('remove_col', 10);
   * ```
   */
  this.alter = function (action, index, amount, source, keepEmptyRows) {
    grid.alter(action, index, amount, source, keepEmptyRows);
  };

  /**
   * Returns a TD element for the given `row` and `col` arguments, if it is rendered on screen.
   * Returns `null` if the TD is not rendered on screen (probably because that part of the table is not visible).
   *
   * @memberof Core#
   * @function getCell
   * @param {Number} row Visual row index.
   * @param {Number} col Visual column index.
   * @param {Boolean} topmost If set to true, it returns the TD element from the topmost overlay. For example,
   * if the wanted cell is in the range of fixed rows, it will return a TD element from the `top` overlay.
   * @returns {Element} The cell's TD element.
   */
  this.getCell = function (row, col, topmost) {
    return instance.view.getCellAtCoords(new _src.CellCoords(row, col), topmost);
  };

  /**
   * Returns the coordinates of the cell, provided as a HTML Element.
   *
   * @memberof Core#
   * @function getCoords
   * @param {Element} elem The HTML Element representing the cell.
   * @returns {CellCoords} Visual coordinates object.
   */
  this.getCoords = function (elem) {
    return this.view.wt.wtTable.getCoords.call(this.view.wt.wtTable, elem);
  };

  /**
   * Returns the property name that corresponds with the given column index. {@link DataMap#colToProp}
   * If the data source is an array of arrays, it returns the columns index.
   *
   * @memberof Core#
   * @function colToProp
   * @param {Number} col Visual column index.
   * @returns {String|Number} Column property or physical column index.
   */
  this.colToProp = function (col) {
    return datamap.colToProp(col);
  };

  /**
   * Returns column index that corresponds with the given property. {@link DataMap#propToCol}
   *
   * @memberof Core#
   * @function propToCol
   * @param {String|Number} prop Property name or physical column index.
   * @returns {Number} Visual column index.
   */
  this.propToCol = function (prop) {
    return datamap.propToCol(prop);
  };

  /**
   * Translate physical row index into visual.
   *
   * @since 0.29.0
   * @memberof Core#
   * @function toVisualRow
   * @param {Number} row Physical row index.
   * @returns {Number} Returns visual row index.
   */
  this.toVisualRow = function (row) {
    return recordTranslator.toVisualRow(row);
  };

  /**
   * Translate physical column index into visual.
   *
   * @since 0.29.0
   * @memberof Core#
   * @function toVisualColumn
   * @param {Number} column Physical column index.
   * @returns {Number} Returns visual column index.
   */
  this.toVisualColumn = function (column) {
    return recordTranslator.toVisualColumn(column);
  };

  /**
   * Translate visual row index into physical.
   * If displayed rows order is different than the order of rows stored in memory (i.e. sorting is applied)
   * to retrieve valid physical row index you can use this method.
   *
   * @since 0.29.0
   * @memberof Core#
   * @function toPhysicalRow
   * @param {Number} row Visual row index.
   * @returns {Number} Returns physical row index.
   */
  this.toPhysicalRow = function (row) {
    return recordTranslator.toPhysicalRow(row);
  };

  /**
   * Translate visual column index into physical.
   * If displayed columns order is different than the order of columns stored in memory (i.e. manual column move is applied)
   * to retrieve valid physical column index you can use this method.
   *
   * @since 0.29.0
   * @memberof Core#
   * @function toPhysicalColumn
   * @param {Number} column Visual column index.
   * @returns {Number} Returns physical column index.
   */
  this.toPhysicalColumn = function (column) {
    return recordTranslator.toPhysicalColumn(column);
  };

  /**
   * @description
   * Returns the cell value at `row`, `col`. `row` and `col` are the __visible__ indexes (note, that if columns were reordered or sorted,
   * the currently visible order will be used).
   *
   * @memberof Core#
   * @function getDataAtCell
   * @param {Number} row Visual row index.
   * @param {Number} col Visual column index.
   * @returns {String|Boolean|null} Data at cell.
   */
  this.getDataAtCell = function (row, col) {
    return datamap.get(row, datamap.colToProp(col));
  };

  /**
   * Return value at `row`, `prop`. (Uses {@link DataMap#get})
   *
   * @memberof Core#
   * @function getDataAtRowProp
   * @param {Number} row Visual row index.
   * @param {String} prop Property name.
   * @returns {*} Cell value.
   */
  this.getDataAtRowProp = function (row, prop) {
    return datamap.get(row, prop);
  };

  /**
   * @description
   * Returns array of column values from the data source. `col` is the __visible__ index of the column.
   * Note, that if columns were reordered or sorted, the currently visible order will be used.
   *
   * @memberof Core#
   * @function getDataAtCol
   * @since 0.9-beta2
   * @param {Number} col Visual column index.
   * @returns {Array} Array of cell values.
   */
  this.getDataAtCol = function (col) {
    var out = [];
    return out.concat.apply(out, _toConsumableArray(datamap.getRange(new _src.CellCoords(0, col), new _src.CellCoords(priv.settings.data.length - 1, col), datamap.DESTINATION_RENDERER)));
  };

  /**
   * Given the object property name (e.g. `'first.name'`), returns an array of column's values from the data source.
   * You can also provide a column index as the first argument.
   *
   * @memberof Core#
   * @function getDataAtProp
   * @since 0.9-beta2
   * @param {String|Number} prop Property name / physical column index.
   * @returns {Array} Array of cell values.
   */
  // TODO: Getting data from `datamap` should work on visual indexes.
  this.getDataAtProp = function (prop) {
    var out = [],
        range;

    range = datamap.getRange(new _src.CellCoords(0, datamap.propToCol(prop)), new _src.CellCoords(priv.settings.data.length - 1, datamap.propToCol(prop)), datamap.DESTINATION_RENDERER);

    return out.concat.apply(out, _toConsumableArray(range));
  };

  /**
   * Returns the source data object (the same that was passed by `data` configuration option or `loadData` method).
   * Optionally you can provide a cell range by using the `row`, `col`, `row2`, `col2` arguments, to get only a fragment of grid data.
   *
   * @memberof Core#
   * @function getSourceData
   * @since 0.20.0
   * @param {Number} [r] From physical row index.
   * @param {Number} [c] From physical column index (or visual index, if data type is an array of objects).
   * @param {Number} [r2] To physical row index.
   * @param {Number} [c2] To physical column index (or visual index, if data type is an array of objects).
   * @returns {Array} Array of grid data.
   */
  this.getSourceData = function (r, c, r2, c2) {
    var data = void 0;

    if (r === void 0) {
      data = dataSource.getData();
    } else {
      data = dataSource.getByRange(new _src.CellCoords(r, c), new _src.CellCoords(r2, c2));
    }

    return data;
  };

  /**
   * Returns the source data object as an arrays of arrays format even when source data was provided in another format.
   * Optionally you can provide a cell range by using the `row`, `col`, `row2`, `col2` arguments, to get only a fragment of grid data.
   *
   * @memberof Core#
   * @function getSourceDataArray
   * @since 0.28.0
   * @param {Number} [r] From physical row index.
   * @param {Number} [c] From physical column index (or visual index, if data type is an array of objects).
   * @param {Number} [r2] To physical row index.
   * @param {Number} [c2] To physical column index (or visual index, if data type is an array of objects).
   * @returns {Array} An array of arrays.
   */
  this.getSourceDataArray = function (r, c, r2, c2) {
    var data = void 0;

    if (r === void 0) {
      data = dataSource.getData(true);
    } else {
      data = dataSource.getByRange(new _src.CellCoords(r, c), new _src.CellCoords(r2, c2), true);
    }

    return data;
  };

  /**
   * Returns an array of column values from the data source. `col` is the index of the row in the data source.
   *
   * @memberof Core#
   * @function getSourceDataAtCol
   * @since 0.11.0-beta3
   * @param {Number} column Visual column index.
   * @returns {Array} Array of the column's cell values.
   */
  // TODO: Getting data from `sourceData` should work always on physical indexes.
  this.getSourceDataAtCol = function (column) {
    return dataSource.getAtColumn(column);
  };

  /**
   * Returns a single row of the data (array or object, depending on what you have). `row` is the index of the row in the data source.
   *
   * @memberof Core#
   * @function getSourceDataAtRow
   * @since 0.11.0-beta3
   * @param {Number} row Physical row index.
   * @returns {Array|Object} Single row of data.
   */
  this.getSourceDataAtRow = function (row) {
    return dataSource.getAtRow(row);
  };

  /**
   * Returns a single value from the data source.
   *
   * @memberof Core#
   * @function getSourceDataAtCell
   * @param {Number} row Physical row index.
   * @param {Number} column Visual column index.
   * @returns {*} Cell data.
   * @since 0.20.0
   */
  // TODO: Getting data from `sourceData` should work always on physical indexes.
  this.getSourceDataAtCell = function (row, column) {
    return dataSource.getAtCell(row, column);
  };

  /**
   * @description
   * Returns a single row of the data. The `row` argument is the __visible__ index of the row.
   *
   * @memberof Core#
   * @function getDataAtRow
   * @param {Number} row Visual row index.
   * @returns {Array} Array of row's cell data.
   * @since 0.9-beta2
   */
  this.getDataAtRow = function (row) {
    var data = datamap.getRange(new _src.CellCoords(row, 0), new _src.CellCoords(row, this.countCols() - 1), datamap.DESTINATION_RENDERER);

    return data[0] || [];
  };

  /**
   * @description
   * Returns a data type defined in the Handsontable settings under the `type` key ([Options#type](http://docs.handsontable.com/Options.html#type)).
   * If there are cells with different types in the selected range, it returns `'mixed'`.
   *
   * @since 0.18.1
   * @memberof Core#
   * @function getDataType
   * @param {Number} rowFrom From visual row index.
   * @param {Number} columnFrom From visual column index.
   * @param {Number} rowTo To visual row index.
   * @param {Number} columnTo To visual column index.
   * @returns {String} Cell type (e.q: `'mixed'`, `'text'`, `'numeric'`, `'autocomplete'`).
   */
  this.getDataType = function (rowFrom, columnFrom, rowTo, columnTo) {
    var _this = this;

    var previousType = null;
    var currentType = null;

    if (rowFrom === void 0) {
      rowFrom = 0;
      rowTo = this.countRows();
      columnFrom = 0;
      columnTo = this.countCols();
    }
    if (rowTo === void 0) {
      rowTo = rowFrom;
    }
    if (columnTo === void 0) {
      columnTo = columnFrom;
    }
    var type = 'mixed';

    (0, _number.rangeEach)(Math.min(rowFrom, rowTo), Math.max(rowFrom, rowTo), function (row) {
      var isTypeEqual = true;

      (0, _number.rangeEach)(Math.min(columnFrom, columnTo), Math.max(columnFrom, columnTo), function (column) {
        var cellType = _this.getCellMeta(row, column);

        currentType = cellType.type;

        if (previousType) {
          isTypeEqual = previousType === currentType;
        } else {
          previousType = currentType;
        }

        return isTypeEqual;
      });
      type = isTypeEqual ? currentType : 'mixed';

      return isTypeEqual;
    });

    return type;
  };

  /**
   * Remove a property defined by the `key` argument from the cell meta object for the provided `row` and `col` coordinates.
   *
   * @memberof Core#
   * @function removeCellMeta
   * @param {Number} row Visual row index.
   * @param {Number} col Visual column index.
   * @param {String} key Property name.
   * @fires Hooks#beforeRemoveCellMeta
   * @fires Hooks#afterRemoveCellMeta
   */
  this.removeCellMeta = function (row, col, key) {
    var _recordTranslator$toP = recordTranslator.toPhysical(row, col),
        _recordTranslator$toP2 = _slicedToArray(_recordTranslator$toP, 2),
        physicalRow = _recordTranslator$toP2[0],
        physicalColumn = _recordTranslator$toP2[1];

    var cachedValue = priv.cellSettings[physicalRow][physicalColumn][key];

    var hookResult = instance.runHooks('beforeRemoveCellMeta', row, col, key, cachedValue);

    if (hookResult !== false) {
      delete priv.cellSettings[physicalRow][physicalColumn][key];

      instance.runHooks('afterRemoveCellMeta', row, col, key, cachedValue);
    }

    cachedValue = null;
  };

  /**
   * Remove one or more rows from the cell meta object.
   *
   * @since 0.30.0
   * @param {Number} index An integer that specifies at what position to add/remove items, Use negative values to specify the position from the end of the array.
   * @param {Number} deleteAmount The number of items to be removed. If set to 0, no items will be removed.
   * @param {Array} items The new items to be added to the array.
   */
  this.spliceCellsMeta = function (index, deleteAmount) {
    var _priv$cellSettings;

    for (var _len2 = arguments.length, items = Array(_len2 > 2 ? _len2 - 2 : 0), _key = 2; _key < _len2; _key++) {
      items[_key - 2] = arguments[_key];
    }

    (_priv$cellSettings = priv.cellSettings).splice.apply(_priv$cellSettings, [index, deleteAmount].concat(items));
  };

  /**
   * Set cell meta data object defined by `prop` to the corresponding params `row` and `col`.
   *
   * @memberof Core#
   * @function setCellMetaObject
   * @since 0.11
   * @param {Number} row Visual row index.
   * @param {Number} col Visual column index.
   * @param {Object} prop Meta object.
   */
  this.setCellMetaObject = function (row, col, prop) {
    if ((typeof prop === 'undefined' ? 'undefined' : _typeof(prop)) === 'object') {
      for (var key in prop) {
        if ((0, _object.hasOwnProperty)(prop, key)) {
          var value = prop[key];
          this.setCellMeta(row, col, key, value);
        }
      }
    }
  };

  /**
   * Sets a property defined by the `key` object to the meta object of a cell corresponding to params `row` and `col`.
   *
   * @memberof Core#
   * @function setCellMeta
   * @since 0.11
   * @param {Number} row Visual row index.
   * @param {Number} col Visual column index.
   * @param {String} key Property name.
   * @param {String} val Property value.
   * @fires Hooks#afterSetCellMeta
   */
  this.setCellMeta = function (row, col, key, val) {
    var _recordTranslator$toP3 = recordTranslator.toPhysical(row, col),
        _recordTranslator$toP4 = _slicedToArray(_recordTranslator$toP3, 2),
        physicalRow = _recordTranslator$toP4[0],
        physicalColumn = _recordTranslator$toP4[1];

    if (!priv.columnSettings[physicalColumn]) {
      priv.columnSettings[physicalColumn] = (0, _setting.columnFactory)(GridSettings, priv.columnsSettingConflicts);
    }

    if (!priv.cellSettings[physicalRow]) {
      priv.cellSettings[physicalRow] = [];
    }
    if (!priv.cellSettings[physicalRow][physicalColumn]) {
      priv.cellSettings[physicalRow][physicalColumn] = new priv.columnSettings[physicalColumn]();
    }
    priv.cellSettings[physicalRow][physicalColumn][key] = val;
    instance.runHooks('afterSetCellMeta', row, col, key, val);
  };

  /**
   * Get all the cells meta settings at least once generated in the table (in order of cell initialization).
   *
   * @since 0.19.0
   * @returns {Array} Returns Array of ColumnSettings object.
   */
  this.getCellsMeta = function () {
    return (0, _array.arrayFlatten)(priv.cellSettings);
  };

  /**
   * Returns the cell properties object for the given `row` and `col` coordinates.
   *
   * @memberof Core#
   * @function getCellMeta
   * @param {Number} row Visual row index.
   * @param {Number} col Visual column index.
   * @returns {Object} The cell properties object.
   * @fires Hooks#beforeGetCellMeta
   * @fires Hooks#afterGetCellMeta
   */
  this.getCellMeta = function (row, col) {
    var prop = datamap.colToProp(col);
    var cellProperties = void 0;

    var _recordTranslator$toP5 = recordTranslator.toPhysical(row, col),
        _recordTranslator$toP6 = _slicedToArray(_recordTranslator$toP5, 2),
        physicalRow = _recordTranslator$toP6[0],
        physicalColumn = _recordTranslator$toP6[1];

    if (!priv.columnSettings[physicalColumn]) {
      priv.columnSettings[physicalColumn] = (0, _setting.columnFactory)(GridSettings, priv.columnsSettingConflicts);
    }

    if (!priv.cellSettings[physicalRow]) {
      priv.cellSettings[physicalRow] = [];
    }
    if (!priv.cellSettings[physicalRow][physicalColumn]) {
      priv.cellSettings[physicalRow][physicalColumn] = new priv.columnSettings[physicalColumn]();
    }

    cellProperties = priv.cellSettings[physicalRow][physicalColumn]; // retrieve cellProperties from cache

    cellProperties.row = physicalRow;
    cellProperties.col = physicalColumn;
    cellProperties.visualRow = row;
    cellProperties.visualCol = col;
    cellProperties.prop = prop;
    cellProperties.instance = instance;

    instance.runHooks('beforeGetCellMeta', row, col, cellProperties);
    (0, _object.extend)(cellProperties, expandType(cellProperties)); // for `type` added in beforeGetCellMeta

    if (cellProperties.cells) {
      var settings = cellProperties.cells.call(cellProperties, physicalRow, physicalColumn, prop);

      if (settings) {
        (0, _object.extend)(cellProperties, settings);
        (0, _object.extend)(cellProperties, expandType(settings)); // for `type` added in cells
      }
    }

    instance.runHooks('afterGetCellMeta', row, col, cellProperties);

    return cellProperties;
  };

  /**
   * Returns a row off the cell meta array.
   *
   * @memberof Core#
   * @function getCellMetaAtRow
   * @since 0.30.0
   * @param {Number} row Physical index of the row to return cell meta for.
   * @returns {Array}
   */
  this.getCellMetaAtRow = function (row) {
    return priv.cellSettings[row];
  };

  /**
   * Checks if the data format and config allows user to modify the column structure.
   * @returns {boolean}
   */
  this.isColumnModificationAllowed = function () {
    return !(instance.dataType === 'object' || instance.getSettings().columns);
  };

  var rendererLookup = (0, _data.cellMethodLookupFactory)('renderer');

  /**
   * Returns the cell renderer function by given `row` and `col` arguments.
   *
   * @memberof Core#
   * @function getCellRenderer
   * @since 0.11
   * @param {Number|Object} row Visual row index or cell meta object.
   * @param {Number} [col] Visual column index.
   * @returns {Function} The renderer function.
   */
  this.getCellRenderer = function (row, col) {
    return (0, _renderers.getRenderer)(rendererLookup.call(this, row, col));
  };

  /**
   * Returns the cell editor by the provided `row` and `col` arguments.
   *
   * @memberof Core#
   * @function getCellEditor
   * @param {Number} row Visual row index.
   * @param {Number} col Visual column index.
   * @returns {Object} The Editor object.
   */
  this.getCellEditor = (0, _data.cellMethodLookupFactory)('editor');

  var validatorLookup = (0, _data.cellMethodLookupFactory)('validator');

  /**
   * Returns the cell validator by `row` and `col`, provided a validator is defined. If not - it doesn't return anything.
   *
   * @memberof Core#
   * @function getCellValidator
   * @param {Number} row Visual row index.
   * @param {Number} col Visual column index.
   * @returns {Function|RegExp|undefined} The validator function.
   */
  this.getCellValidator = function (row, col) {
    var validator = validatorLookup.call(this, row, col);

    if (typeof validator === 'string') {
      validator = (0, _validators.getValidator)(validator);
    }

    return validator;
  };

  /**
   * Validates all cells using their validator functions and calls callback when finished.
   *
   * If one of the cells is invalid, the callback will be fired with `'valid'` arguments as `false` - otherwise it would equal `true`.
   *
   * @memberof Core#
   * @function validateCells
   * @param {Function} [callback] The callback function.
   */
  this.validateCells = function (callback) {
    var waitingForValidator = new ValidatorsQueue();

    if (callback) {
      waitingForValidator.onQueueEmpty = callback;
    }

    var i = instance.countRows() - 1;

    while (i >= 0) {
      var j = instance.countCols() - 1;

      while (j >= 0) {
        waitingForValidator.addValidatorToQueue();

        instance.validateCell(instance.getDataAtCell(i, j), instance.getCellMeta(i, j), function (result) {
          if (typeof result !== 'boolean') {
            throw new Error('Validation error: result is not boolean');
          }
          if (result === false) {
            waitingForValidator.valid = false;
          }
          waitingForValidator.removeValidatorFormQueue();
        }, 'validateCells');
        j--;
      }
      i--;
    }
    waitingForValidator.checkIfQueueIsEmpty();
  };

  /**
   * Returns an array of row headers' values (if they are enabled). If param `row` was given, it returns the header of the given row as a string.
   *
   * @memberof Core#
   * @function getRowHeader
   * @param {Number} [row] Visual row index.
   * @fires Hooks#modifyRowHeader
   * @returns {Array|String} Array of header values / single header value.
   */
  this.getRowHeader = function (row) {
    var rowHeader = priv.settings.rowHeaders;

    if (row !== void 0) {
      row = instance.runHooks('modifyRowHeader', row);
    }
    if (row === void 0) {
      rowHeader = [];
      (0, _number.rangeEach)(instance.countRows() - 1, function (i) {
        rowHeader.push(instance.getRowHeader(i));
      });
    } else if (Array.isArray(rowHeader) && rowHeader[row] !== void 0) {
      rowHeader = rowHeader[row];
    } else if ((0, _function.isFunction)(rowHeader)) {
      rowHeader = rowHeader(row);
    } else if (rowHeader && typeof rowHeader !== 'string' && typeof rowHeader !== 'number') {
      rowHeader = row + 1;
    }

    return rowHeader;
  };

  /**
   * Returns information about if this table is configured to display row headers.
   *
   * @memberof Core#
   * @function hasRowHeaders
   * @returns {Boolean} `true` if the instance has the row headers enabled, `false` otherwise.
   * @since 0.11
   */
  this.hasRowHeaders = function () {
    return !!priv.settings.rowHeaders;
  };

  /**
   * Returns information about if this table is configured to display column headers.
   *
   * @memberof Core#
   * @function hasColHeaders
   * @since 0.11
   * @returns {Boolean} `True` if the instance has the column headers enabled, `false` otherwise.
   */
  this.hasColHeaders = function () {
    if (priv.settings.colHeaders !== void 0 && priv.settings.colHeaders !== null) {
      // Polymer has empty value = null
      return !!priv.settings.colHeaders;
    }
    for (var i = 0, ilen = instance.countCols(); i < ilen; i++) {
      if (instance.getColHeader(i)) {
        return true;
      }
    }

    return false;
  };

  /**
   * Returns an array of column headers (in string format, if they are enabled). If param `col` is given, it returns the header at the given column as a string.
   *
   * @memberof Core#
   * @function getColHeader
   * @param {Number} [col] Visual column index.
   * @fires Hooks#modifyColHeader
   * @returns {Array|String} The column header(s).
   */
  this.getColHeader = function (col) {
    var columnsAsFunc = priv.settings.columns && (0, _function.isFunction)(priv.settings.columns);
    var result = priv.settings.colHeaders;

    col = instance.runHooks('modifyColHeader', col);

    if (col === void 0) {
      var out = [];
      var ilen = columnsAsFunc ? instance.countSourceCols() : instance.countCols();

      for (var i = 0; i < ilen; i++) {
        out.push(instance.getColHeader(i));
      }

      result = out;
    } else {
      var translateVisualIndexToColumns = function translateVisualIndexToColumns(col) {
        var arr = [];
        var columnsLen = instance.countSourceCols();
        var index = 0;

        for (; index < columnsLen; index++) {
          if ((0, _function.isFunction)(instance.getSettings().columns) && instance.getSettings().columns(index)) {
            arr.push(index);
          }
        }

        return arr[col];
      };
      var baseCol = col;
      col = instance.runHooks('modifyCol', col);

      var prop = translateVisualIndexToColumns(col);

      if (priv.settings.columns && (0, _function.isFunction)(priv.settings.columns) && priv.settings.columns(prop) && priv.settings.columns(prop).title) {
        result = priv.settings.columns(prop).title;
      } else if (priv.settings.columns && priv.settings.columns[col] && priv.settings.columns[col].title) {
        result = priv.settings.columns[col].title;
      } else if (Array.isArray(priv.settings.colHeaders) && priv.settings.colHeaders[col] !== void 0) {
        result = priv.settings.colHeaders[col];
      } else if ((0, _function.isFunction)(priv.settings.colHeaders)) {
        result = priv.settings.colHeaders(col);
      } else if (priv.settings.colHeaders && typeof priv.settings.colHeaders !== 'string' && typeof priv.settings.colHeaders !== 'number') {
        result = (0, _data.spreadsheetColumnLabel)(baseCol); // see #1458
      }
    }

    return result;
  };

  /**
   * Return column width from settings (no guessing). Private use intended.
   *
   * @private
   * @memberof Core#
   * @function _getColWidthFromSettings
   * @param {Number} col Visual col index.
   * @returns {Number}
   */
  this._getColWidthFromSettings = function (col) {
    var cellProperties = instance.getCellMeta(0, col);
    var width = cellProperties.width;

    if (width === void 0 || width === priv.settings.width) {
      width = cellProperties.colWidths;
    }
    if (width !== void 0 && width !== null) {
      switch (typeof width === 'undefined' ? 'undefined' : _typeof(width)) {
        case 'object':
          // array
          width = width[col];
          break;

        case 'function':
          width = width(col);
          break;
        default:
          break;
      }
      if (typeof width === 'string') {
        width = parseInt(width, 10);
      }
    }

    return width;
  };

  /**
   * Returns the width of the requested column.
   *
   * @memberof Core#
   * @function getColWidth
   * @since 0.11
   * @param {Number} col Visual column index.
   * @returns {Number} Column width.
   * @fires Hooks#modifyColWidth
   */
  this.getColWidth = function (col) {
    var width = instance._getColWidthFromSettings(col);

    width = instance.runHooks('modifyColWidth', width, col);

    if (width === void 0) {
      width = _src.ViewportColumnsCalculator.DEFAULT_WIDTH;
    }

    return width;
  };

  /**
   * Return row height from settings (no guessing). Private use intended.
   *
   * @private
   * @memberof Core#
   * @function _getRowHeightFromSettings
   * @param {Number} row Visual row index.
   * @returns {Number}
   */
  this._getRowHeightFromSettings = function (row) {
    // let cellProperties = instance.getCellMeta(row, 0);
    // let height = cellProperties.height;
    //
    // if (height === void 0 || height === priv.settings.height) {
    //  height = cellProperties.rowHeights;
    // }
    var height = priv.settings.rowHeights;

    if (height !== void 0 && height !== null) {
      switch (typeof height === 'undefined' ? 'undefined' : _typeof(height)) {
        case 'object':
          // array
          height = height[row];
          break;

        case 'function':
          height = height(row);
          break;
        default:
          break;
      }
      if (typeof height === 'string') {
        height = parseInt(height, 10);
      }
    }

    return height;
  };

  /**
   * Returns the row height.
   *
   * @memberof Core#
   * @function getRowHeight
   * @since 0.11
   * @param {Number} row Visual row index.
   * @returns {Number} The given row's height.
   * @fires Hooks#modifyRowHeight
   */
  this.getRowHeight = function (row) {
    var height = instance._getRowHeightFromSettings(row);

    height = instance.runHooks('modifyRowHeight', height, row);

    return height;
  };

  /**
   * Returns the total number of rows in the data source.
   *
   * @memberof Core#
   * @function countSourceRows
   * @since 0.20.0
   * @returns {Number} Total number in rows in data source.
   */
  this.countSourceRows = function () {
    var sourceLength = instance.runHooks('modifySourceLength');
    return sourceLength || (instance.getSourceData() ? instance.getSourceData().length : 0);
  };

  /**
   * Returns the total number of columns in the data source.
   *
   * @memberof Core#
   * @function countSourceCols
   * @since 0.26.1
   * @returns {Number} Total number in columns in data source.
   */
  this.countSourceCols = function () {
    var len = 0;
    var obj = instance.getSourceData() && instance.getSourceData()[0] ? instance.getSourceData()[0] : [];

    if ((0, _object.isObject)(obj)) {
      len = (0, _object.deepObjectSize)(obj);
    } else {
      len = obj.length || 0;
    }

    return len;
  };

  /**
   * Returns the total number of rows in the grid.
   *
   * @memberof Core#
   * @function countRows
   * @returns {Number} Total number in rows the grid.
   */
  this.countRows = function () {
    return datamap.getLength();
  };

  /**
   * Returns the total number of columns in the grid.
   *
   * @memberof Core#
   * @function countCols
   * @returns {Number} Total number of columns.
   */
  this.countCols = function () {
    var maxCols = this.getSettings().maxCols;
    var dataHasLength = false;
    var dataLen = 0;

    if (instance.dataType === 'array') {
      dataHasLength = priv.settings.data && priv.settings.data[0] && priv.settings.data[0].length;
    }

    if (dataHasLength) {
      dataLen = priv.settings.data[0].length;
    }

    if (priv.settings.columns) {
      var columnsIsFunction = (0, _function.isFunction)(priv.settings.columns);

      if (columnsIsFunction) {
        if (instance.dataType === 'array') {
          var columnLen = 0;

          for (var i = 0; i < dataLen; i++) {
            if (priv.settings.columns(i)) {
              columnLen++;
            }
          }

          dataLen = columnLen;
        } else if (instance.dataType === 'object' || instance.dataType === 'function') {
          dataLen = datamap.colToPropCache.length;
        }
      } else {
        dataLen = priv.settings.columns.length;
      }
    } else if (instance.dataType === 'object' || instance.dataType === 'function') {
      dataLen = datamap.colToPropCache.length;
    }

    return Math.min(maxCols, dataLen);
  };

  /**
   * Returns an visual index of the first rendered row.
   *
   * @memberof Core#
   * @function rowOffset
   * @returns {Number} Visual index of first rendered row.
   */
  this.rowOffset = function () {
    return instance.view.wt.wtTable.getFirstRenderedRow();
  };

  /**
   * Returns the visual index of the first rendered column.
   *
   * @memberof Core#
   * @function colOffset
   * @returns {Number} Visual index of the first visible column.
   */
  this.colOffset = function () {
    return instance.view.wt.wtTable.getFirstRenderedColumn();
  };

  /**
   * Returns the number of rendered rows (including rows partially or fully rendered outside viewport).
   *
   * @memberof Core#
   * @function countRenderedRows
   * @returns {Number} Returns -1 if table is not visible.
   */
  this.countRenderedRows = function () {
    return instance.view.wt.drawn ? instance.view.wt.wtTable.getRenderedRowsCount() : -1;
  };

  /**
   * Returns the number of visible rows (rendered rows that fully fit inside viewport).
   *
   * @memberof Core#
   * @function countVisibleRows
   * @returns {Number} Number of visible rows or -1.
   */
  this.countVisibleRows = function () {
    return instance.view.wt.drawn ? instance.view.wt.wtTable.getVisibleRowsCount() : -1;
  };

  /**
   * Returns the number of rendered columns (including columns partially or fully rendered outside viewport).
   *
   * @memberof Core#
   * @function countRenderedCols
   * @returns {Number} Returns -1 if table is not visible.
   */
  this.countRenderedCols = function () {
    return instance.view.wt.drawn ? instance.view.wt.wtTable.getRenderedColumnsCount() : -1;
  };

  /**
   * Returns the number of visible columns. Returns -1 if table is not visible
   *
   * @memberof Core#
   * @function countVisibleCols
   * @return {Number} Number of visible columns or -1.
   */
  this.countVisibleCols = function () {
    return instance.view.wt.drawn ? instance.view.wt.wtTable.getVisibleColumnsCount() : -1;
  };

  /**
   * Returns the number of empty rows. If the optional ending parameter is `true`, returns the
   * number of empty rows at the bottom of the table.
   *
   * @memberof Core#
   * @function countEmptyRows
   * @param {Boolean} [ending] If `true`, will only count empty rows at the end of the data source.
   * @returns {Number} Count empty rows
   * @fires Hooks#modifyRow
   */
  this.countEmptyRows = function (ending) {
    var i = instance.countRows() - 1,
        empty = 0,
        row;

    while (i >= 0) {
      row = instance.runHooks('modifyRow', i);

      if (instance.isEmptyRow(row)) {
        empty++;
      } else if (ending) {
        break;
      }
      i--;
    }

    return empty;
  };

  /**
   * Returns the number of empty columns. If the optional ending parameter is `true`, returns the number of empty
   * columns at right hand edge of the table.
   *
   * @memberof Core#
   * @function countEmptyCols
   * @param {Boolean} [ending] If `true`, will only count empty columns at the end of the data source row.
   * @returns {Number} Count empty cols
   */
  this.countEmptyCols = function (ending) {
    if (instance.countRows() < 1) {
      return 0;
    }
    var i = instance.countCols() - 1,
        empty = 0;

    while (i >= 0) {
      if (instance.isEmptyCol(i)) {
        empty++;
      } else if (ending) {
        break;
      }
      i--;
    }

    return empty;
  };

  /**
   * Check if all cells in the row declared by the `row` argument are empty.
   *
   * @memberof Core#
   * @function isEmptyRow
   * @param {Number} row Row index.
   * @returns {Boolean} `true` if the row at the given `row` is empty, `false` otherwise.
   */
  this.isEmptyRow = function (row) {
    return priv.settings.isEmptyRow.call(instance, row);
  };

  /**
   * Check if all cells in the the column declared by the `col` argument are empty.
   *
   * @memberof Core#
   * @function isEmptyCol
   * @param {Number} col Column index.
   * @returns {Boolean} `true` if the column at the given `col` is empty, `false` otherwise.
   */
  this.isEmptyCol = function (col) {
    return priv.settings.isEmptyCol.call(instance, col);
  };

  /**
   * Select cell specified by `row` and `col` values or a range of cells finishing at `endRow`, `endCol`.
   * By default, viewport will be scrolled to selection.
   * After the `selectCell` method had finished, the instance will be listening to keyboard input on the document.
   *
   * @memberof Core#
   * @function selectCell
   * @param {Number} row Visual row index.
   * @param {Number} col Visual column index.
   * @param {Number} [endRow] Visual end row index (if selecting a range).
   * @param {Number} [endCol] Visual end column index (if selecting a range).
   * @param {Boolean} [scrollToCell=true] If `true`, the viewport will be scrolled to the selection.
   * @param {Boolean} [changeListener=true] If `false`, Handsontable will not change keyboard events listener to himself.
   * @returns {Boolean} `true` if selection was successful, `false` otherwise.
   */
  this.selectCell = function (row, col, endRow, endCol, scrollToCell, changeListener) {
    var coords;

    changeListener = (0, _mixed.isUndefined)(changeListener) || changeListener === true;

    if (typeof row !== 'number' || row < 0 || row >= instance.countRows()) {
      return false;
    }
    if (typeof col !== 'number' || col < 0 || col >= instance.countCols()) {
      return false;
    }
    if ((0, _mixed.isDefined)(endRow)) {
      if (typeof endRow !== 'number' || endRow < 0 || endRow >= instance.countRows()) {
        return false;
      }
      if (typeof endCol !== 'number' || endCol < 0 || endCol >= instance.countCols()) {
        return false;
      }
    }
    coords = new _src.CellCoords(row, col);
    priv.selRange = new _src.CellRange(coords, coords, coords);

    if (changeListener) {
      instance.listen();
    }

    if ((0, _mixed.isUndefined)(endRow)) {
      selection.setRangeEnd(priv.selRange.from, scrollToCell);
    } else {
      selection.setRangeEnd(new _src.CellCoords(endRow, endCol), scrollToCell);
    }
    instance.selection.finish();

    return true;
  };

  /**
   * Select the cell specified by the `row` and `prop` arguments, or a range finishing at `endRow`, `endProp`.
   * By default, viewport will be scrolled to selection.
   *
   * @memberof Core#
   * @function selectCellByProp
   * @param {Number} row Visual row index.
   * @param {String} prop Property name.
   * @param {Number} [endRow] visual end row index (if selecting a range).
   * @param {String} [endProp] End property name (if selecting a range).
   * @param {Boolean} [scrollToCell=true] If `true`, viewport will be scrolled to the selection.
   * @returns {Boolean} `true` if selection was successful, `false` otherwise.
   */
  this.selectCellByProp = function (row, prop, endRow, endProp, scrollToCell) {
    var _instance5;

    arguments[1] = datamap.propToCol(arguments[1]);

    if ((0, _mixed.isDefined)(arguments[3])) {
      arguments[3] = datamap.propToCol(arguments[3]);
    }

    return (_instance5 = instance).selectCell.apply(_instance5, arguments);
  };

  /**
   * Deselects the current cell selection on grid.
   *
   * @memberof Core#
   * @function deselectCell
   */
  this.deselectCell = function () {
    selection.deselect();
  };

  /**
   * Scroll viewport to coords specified by the `row` and `column` arguments.
   *
   * @since 0.24.3
   * @memberof Core#
   * @function scrollViewportTo
   * @param {Number} [row] Visual row index.
   * @param {Number} [column] Visual column index.
   * @param {Boolean} [snapToBottom = false] If `true`, viewport is scrolled to show the cell on the bottom of the table.
   * @param {Boolean} [snapToRight = false] If `true`, viewport is scrolled to show the cell on the right side of the table.
   * @returns {Boolean} `true` if scroll was successful, `false` otherwise.
   */
  this.scrollViewportTo = function (row, column) {
    var snapToBottom = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
    var snapToRight = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;

    if (row !== void 0 && (row < 0 || row >= instance.countRows())) {
      return false;
    }
    if (column !== void 0 && (column < 0 || column >= instance.countCols())) {
      return false;
    }

    var result = false;

    if (row !== void 0 && column !== void 0) {
      instance.view.wt.wtOverlays.topOverlay.scrollTo(row, snapToBottom);
      instance.view.wt.wtOverlays.leftOverlay.scrollTo(column, snapToRight);

      result = true;
    }
    if (typeof row === 'number' && typeof column !== 'number') {
      instance.view.wt.wtOverlays.topOverlay.scrollTo(row, snapToBottom);

      result = true;
    }
    if (typeof column === 'number' && typeof row !== 'number') {
      instance.view.wt.wtOverlays.leftOverlay.scrollTo(column, snapToRight);

      result = true;
    }

    return result;
  };

  /**
   * Removes grid from the DOM.
   *
   * @memberof Core#
   * @function destroy
   * @fires Hooks#afterDestroy
   */
  this.destroy = function () {

    instance._clearTimeouts();
    if (instance.view) {
      // in case HT is destroyed before initialization has finished
      instance.view.destroy();
    }
    if (dataSource) {
      dataSource.destroy();
    }
    dataSource = null;

    var nextSibling = instance.rootElement.nextSibling;

    if ((0, _rootInstance.isRootInstance)(instance) && nextSibling) {
      instance.rootElement.parentNode.removeChild(nextSibling);
    }
    (0, _element.empty)(instance.rootElement);
    eventManager.destroy();

    instance.runHooks('afterDestroy');
    _pluginHooks2.default.getSingleton().destroy(instance);

    for (var i in instance) {
      if ((0, _object.hasOwnProperty)(instance, i)) {
        // replace instance methods with post mortem
        if ((0, _function.isFunction)(instance[i])) {
          instance[i] = postMortem;
        } else if (i !== 'guid') {
          // replace instance properties with null (restores memory)
          // it should not be necessary but this prevents a memory leak side effects that show itself in Jasmine tests
          instance[i] = null;
        }
      }
    }

    // replace private properties with null (restores memory)
    // it should not be necessary but this prevents a memory leak side effects that show itself in Jasmine tests
    if (datamap) {
      datamap.destroy();
    }
    datamap = null;
    priv = null;
    grid = null;
    selection = null;
    editorManager = null;
    instance = null;
    GridSettings = null;
  };

  /**
   * Replacement for all methods after Handsotnable was destroyed.
   *
   * @private
   */
  function postMortem() {
    throw new Error('This method cannot be called because this Handsontable instance has been destroyed');
  }

  /**
   * Returns the active editor object.
   *
   * @memberof Core#
   * @function getActiveEditor
   * @returns {Object} The active editor object.
   */
  this.getActiveEditor = function () {
    return editorManager.getActiveEditor();
  };

  /**
   * Returns plugin instance using the plugin name provided.
   *
   * @memberof Core#
   * @function getPlugin
   * @param {String} pluginName The plugin name.
   * @returns {*} The plugin instance.
   * @since 0.15.0
   */
  this.getPlugin = function (pluginName) {
    return (0, _plugins.getPlugin)(this, pluginName);
  };

  /**
   * Returns the Handsontable instance.
   *
   * @memberof Core#
   * @function getInstance
   * @returns {Handsontable} The Handsontable instance.
   */
  this.getInstance = function () {
    return instance;
  };

  /**
   * Adds listener to the specified hook name (only for this Handsontable instance).
   *
   * @memberof Core#
   * @function addHook
   * @see Hooks#add
   * @param {String} key Hook name.
   * @param {Function|Array} callback Function or array of Functions.
   *
   * @example
   * ```js
   * hot.addHook('beforeInit', myCallback);
   * ```
   */
  this.addHook = function (key, callback) {
    _pluginHooks2.default.getSingleton().add(key, callback, instance);
  };

  /**
   * Check if for a specified hook name there are added listeners (only for this Handsontable instance).
   *
   * @memberof Core#
   * @function hasHook
   * @see Hooks#has
   * @param {String} key Hook name
   * @return {Boolean}
   *
   * @example
   * ```js
   * var hasBeforeInitListeners = hot.hasHook('beforeInit');
   * ```
   */
  this.hasHook = function (key) {
    return _pluginHooks2.default.getSingleton().has(key, instance);
  };

  /**
   * Adds listener to specified hook name (only for this Handsontable instance).
   * After the listener is triggered, it will be automatically removed.
   *
   * @memberof Core#
   * @function addHookOnce
   * @see Hooks#once
   * @param {String} key Hook name.
   * @param {Function|Array} callback Function or array of Functions.
   *
   * @example
   * ```js
   * hot.addHookOnce('beforeInit', myCallback);
   * ```
   */
  this.addHookOnce = function (key, callback) {
    _pluginHooks2.default.getSingleton().once(key, callback, instance);
  };

  /**
   * Removes the hook listener previously registered with {@link Core#addHook}.
   *
   * @memberof Core#
   * @function removeHook
   * @see Hooks#remove
   * @param {String} key Hook name.
   * @param {Function} callback Function which have been registered via {@link Core#addHook}.
   *
   * @example
   * ```js
   * hot.removeHook('beforeInit', myCallback);
   * ```
   */
  this.removeHook = function (key, callback) {
    _pluginHooks2.default.getSingleton().remove(key, callback, instance);
  };

  /**
   * Run the callbacks for the hook provided in the `key` argument using the parameters given in the other arguments.
   *
   * @memberof Core#
   * @function runHooks
   * @see Hooks#run
   * @param {String} key Hook name.
   * @param {*} [p1] Argument passed to the callback.
   * @param {*} [p2] Argument passed to the callback.
   * @param {*} [p3] Argument passed to the callback.
   * @param {*} [p4] Argument passed to the callback.
   * @param {*} [p5] Argument passed to the callback.
   * @param {*} [p6] Argument passed to the callback.
   * @returns {*}
   *
   * @example
   * ```js
   * hot.runHooks('beforeInit');
   * ```
   */
  this.runHooks = function (key, p1, p2, p3, p4, p5, p6) {
    return _pluginHooks2.default.getSingleton().run(instance, key, p1, p2, p3, p4, p5, p6);
  };

  this.timeouts = [];

  /**
   * Sets timeout. Purpose of this method is to clear all known timeouts when `destroy` method is called.
   *
   * @param {*} handle
   * @private
   */
  this._registerTimeout = function (handle) {
    this.timeouts.push(handle);
  };

  /**
   * Clears all known timeouts.
   *
   * @private
   */
  this._clearTimeouts = function () {
    for (var i = 0, ilen = this.timeouts.length; i < ilen; i++) {
      clearTimeout(this.timeouts[i]);
    }
  };

  /**
   * Handsontable version
   *
   * @type {String}
   */
  // this.version = Handsontable.version;

  _pluginHooks2.default.getSingleton().run(instance, 'construct');
};

/***/ }),
/* 67 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


exports.__esModule = true;
exports.spreadsheetColumnLabel = spreadsheetColumnLabel;
exports.spreadsheetColumnIndex = spreadsheetColumnIndex;
exports.createSpreadsheetData = createSpreadsheetData;
exports.createSpreadsheetObjectData = createSpreadsheetObjectData;
exports.createEmptySpreadsheetData = createEmptySpreadsheetData;
exports.translateRowsToColumns = translateRowsToColumns;
exports.cellMethodLookupFactory = cellMethodLookupFactory;

var _cellTypes = __webpack_require__(65);

var _object = __webpack_require__(3);

var COLUMN_LABEL_BASE = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
var COLUMN_LABEL_BASE_LENGTH = COLUMN_LABEL_BASE.length;

/**
 * Generates spreadsheet-like column names: A, B, C, ..., Z, AA, AB, etc.
 *
 * @param {Number} index Column index.
 * @returns {String}
 */
function spreadsheetColumnLabel(index) {
  var dividend = index + 1;
  var columnLabel = '';
  var modulo = void 0;

  while (dividend > 0) {
    modulo = (dividend - 1) % COLUMN_LABEL_BASE_LENGTH;
    columnLabel = String.fromCharCode(65 + modulo) + columnLabel;
    dividend = parseInt((dividend - modulo) / COLUMN_LABEL_BASE_LENGTH, 10);
  }

  return columnLabel;
}

/**
 * Generates spreadsheet-like column index from theirs labels: A, B, C ...., Z, AA, AB, etc.
 *
 * @param {String} label Column label.
 * @returns {Number}
 */
function spreadsheetColumnIndex(label) {
  var result = 0;

  if (label) {
    for (var i = 0, j = label.length - 1; i < label.length; i += 1, j -= 1) {
      result += Math.pow(COLUMN_LABEL_BASE_LENGTH, j) * (COLUMN_LABEL_BASE.indexOf(label[i]) + 1);
    }
  }
  --result;

  return result;
}

/**
 * Creates 2D array of Excel-like values "A1", "A2", ...
 *
 * @param {Number} rows Number of rows to generate.
 * @param {Number} columns Number of columns to generate.
 * @returns {Array}
 */
function createSpreadsheetData() {
  var rows = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 100;
  var columns = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 4;

  var _rows = [],
      i,
      j;

  for (i = 0; i < rows; i++) {
    var row = [];

    for (j = 0; j < columns; j++) {
      row.push(spreadsheetColumnLabel(j) + (i + 1));
    }
    _rows.push(row);
  }

  return _rows;
}

/**
 * Creates 2D array of Excel-like values "A1", "A2", as an array of objects.
 *
 * @param {Number} rows Number of rows to generate.
 * @param {Number} colCount Number of columns to generate.
 * @returns {Array}
 */
function createSpreadsheetObjectData() {
  var rows = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 100;
  var colCount = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 4;

  var _rows = [],
      i,
      j;

  for (i = 0; i < rows; i++) {
    var row = {};

    for (j = 0; j < colCount; j++) {
      row['prop' + j] = spreadsheetColumnLabel(j) + (i + 1);
    }
    _rows.push(row);
  }

  return _rows;
}

/**
 * Generates an empty data object.
 *
 * @param {Number} rows Number of rows to generate.
 * @param {Number} columns Number of columns to generate
 * @returns {Array}
 */
function createEmptySpreadsheetData(rows, columns) {
  var data = [];
  var row = void 0;

  for (var i = 0; i < rows; i++) {
    row = [];
    for (var j = 0; j < columns; j++) {
      row.push('');
    }
    data.push(row);
  }

  return data;
}

function translateRowsToColumns(input) {
  var i,
      ilen,
      j,
      jlen,
      output = [],
      olen = 0;

  for (i = 0, ilen = input.length; i < ilen; i++) {
    for (j = 0, jlen = input[i].length; j < jlen; j++) {
      if (j == olen) {
        output.push([]);
        olen++;
      }
      output[j].push(input[i][j]);
    }
  }

  return output;
}

/**
 * Factory that produces a function for searching methods (or any properties) which could be defined directly in
 * table configuration or implicitly, within cell type definition.
 *
 * For example: renderer can be defined explicitly using "renderer" property in column configuration or it can be
 * defined implicitly using "type" property.
 *
 * Methods/properties defined explicitly always takes precedence over those defined through "type".
 *
 * If the method/property is not found in an object, searching is continued recursively through prototype chain, until
 * it reaches the Object.prototype.
 *
 *
 * @param methodName {String} name of the method/property to search (i.e. 'renderer', 'validator', 'copyable')
 * @param allowUndefined {Boolean} [optional] if false, the search is continued if methodName has not been found in cell "type"
 * @returns {Function}
 */
function cellMethodLookupFactory(methodName, allowUndefined) {

  allowUndefined = typeof allowUndefined == 'undefined' ? true : allowUndefined;

  return function cellMethodLookup(row, col) {
    return function getMethodFromProperties(properties) {

      if (!properties) {
        return; // method not found
      } else if ((0, _object.hasOwnProperty)(properties, methodName) && properties[methodName] !== void 0) {
        // check if it is own and is not empty
        return properties[methodName]; // method defined directly
      } else if ((0, _object.hasOwnProperty)(properties, 'type') && properties.type) {
        // check if it is own and is not empty
        var type;

        if (typeof properties.type != 'string') {
          throw new Error('Cell type must be a string ');
        }
        type = (0, _cellTypes.getCellType)(properties.type);

        if ((0, _object.hasOwnProperty)(type, methodName)) {
          return type[methodName]; // method defined in type.
        } else if (allowUndefined) {
          return; // method does not defined in type (eg. validator), returns undefined
        }
      }

      return getMethodFromProperties(Object.getPrototypeOf(properties));
    }(typeof row == 'number' ? this.getCellMeta(row, col) : row);
  };
}

/***/ }),
/* 68 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


exports.__esModule = true;
exports.columnFactory = columnFactory;

var _object = __webpack_require__(3);

/* eslint-disable import/prefer-default-export */
/**
 * Factory for columns constructors.
 *
 * @param {Object} GridSettings
 * @param {Array} conflictList
 * @return {Object} ColumnSettings
 */
function columnFactory(GridSettings, conflictList) {
  function ColumnSettings() {};

  (0, _object.inherit)(ColumnSettings, GridSettings);

  // Clear conflict settings
  for (var i = 0, len = conflictList.length; i < len; i++) {
    ColumnSettings.prototype[conflictList[i]] = void 0;
  }

  return ColumnSettings;
}

/***/ }),
/* 69 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


exports.__esModule = true;

var _createClass = 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); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

var _element = __webpack_require__(0);

var _array = __webpack_require__(2);

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

/**
 * @class GhostTable
 * @util
 */
var GhostTable = function () {
  function GhostTable(hotInstance) {
    _classCallCheck(this, GhostTable);

    /**
     * Handsontable instance.
     *
     * @type {Core}
     */
    this.hot = hotInstance;
    /**
     * Container element where every table will be injected.
     *
     * @type {HTMLElement|null}
     */
    this.container = null;
    /**
     * Flag which determine is table was injected to DOM.
     *
     * @type {Boolean}
     */
    this.injected = false;
    /**
     * Added rows collection.
     *
     * @type {Array}
     */
    this.rows = [];
    /**
     * Added columns collection.
     *
     * @type {Array}
     */
    this.columns = [];
    /**
     * Samples prepared for calculations.
     *
     * @type {Map}
     * @default {null}
     */
    this.samples = null;
    /**
     * Ghost table settings.
     *
     * @type {Object}
     * @default {Object}
     */
    this.settings = {
      useHeaders: true
    };
  }

  /**
   * Add row.
   *
   * @param {Number} row Row index.
   * @param {Map} samples Samples Map object.
   */


  _createClass(GhostTable, [{
    key: 'addRow',
    value: function addRow(row, samples) {
      if (this.columns.length) {
        throw new Error('Doesn\'t support multi-dimensional table');
      }
      if (!this.rows.length) {
        this.container = this.createContainer(this.hot.rootElement.className);
      }
      var rowObject = { row: row };
      this.rows.push(rowObject);

      this.samples = samples;
      this.table = this.createTable(this.hot.table.className);
      this.table.colGroup.appendChild(this.createColGroupsCol());
      this.table.tr.appendChild(this.createRow(row));
      this.container.container.appendChild(this.table.fragment);

      rowObject.table = this.table.table;
    }

    /**
     * Add a row consisting of the column headers.
     */

  }, {
    key: 'addColumnHeadersRow',
    value: function addColumnHeadersRow(samples) {
      if (this.hot.getColHeader(0) != null) {
        var rowObject = { row: -1 };
        this.rows.push(rowObject);

        this.container = this.createContainer(this.hot.rootElement.className);

        this.samples = samples;
        this.table = this.createTable(this.hot.table.className);
        this.table.colGroup.appendChild(this.createColGroupsCol());
        this.table.tHead.appendChild(this.createColumnHeadersRow());
        this.container.container.appendChild(this.table.fragment);

        rowObject.table = this.table.table;
      }
    }

    /**
     * Add column.
     *
     * @param {Number} column Column index.
     * @param {Map} samples Samples Map object.
     */

  }, {
    key: 'addColumn',
    value: function addColumn(column, samples) {
      if (this.rows.length) {
        throw new Error('Doesn\'t support multi-dimensional table');
      }
      if (!this.columns.length) {
        this.container = this.createContainer(this.hot.rootElement.className);
      }
      var columnObject = { col: column };
      this.columns.push(columnObject);

      this.samples = samples;
      this.table = this.createTable(this.hot.table.className);

      if (this.getSetting('useHeaders') && this.hot.getColHeader(column) !== null) {
        this.hot.view.appendColHeader(column, this.table.th);
      }
      this.table.tBody.appendChild(this.createCol(column));
      this.container.container.appendChild(this.table.fragment);

      columnObject.table = this.table.table;
    }

    /**
     * Get calculated heights.
     *
     * @param {Function} callback Callback which will be fired for each calculated row.
     */

  }, {
    key: 'getHeights',
    value: function getHeights(callback) {
      if (!this.injected) {
        this.injectTable();
      }
      (0, _array.arrayEach)(this.rows, function (row) {
        // -1 <- reduce border-top from table
        callback(row.row, (0, _element.outerHeight)(row.table) - 1);
      });
    }

    /**
     * Get calculated widths.
     *
     * @param {Function} callback Callback which will be fired for each calculated column.
     */

  }, {
    key: 'getWidths',
    value: function getWidths(callback) {
      if (!this.injected) {
        this.injectTable();
      }
      (0, _array.arrayEach)(this.columns, function (column) {
        callback(column.col, (0, _element.outerWidth)(column.table));
      });
    }

    /**
     * Set the Ghost Table settings to the provided object.
     *
     * @param {Object} settings New Ghost Table Settings
     */

  }, {
    key: 'setSettings',
    value: function setSettings(settings) {
      this.settings = settings;
    }

    /**
     * Set a single setting of the Ghost Table.
     *
     * @param {String} name Setting name.
     * @param {*} value Setting value.
     */

  }, {
    key: 'setSetting',
    value: function setSetting(name, value) {
      if (!this.settings) {
        this.settings = {};
      }

      this.settings[name] = value;
    }

    /**
     * Get the Ghost Table settings.
     *
     * @returns {Object|null}
     */

  }, {
    key: 'getSettings',
    value: function getSettings() {
      return this.settings;
    }

    /**
     * Get a single Ghost Table setting.
     *
     * @param {String} name
     * @returns {Boolean|null}
     */

  }, {
    key: 'getSetting',
    value: function getSetting(name) {
      if (this.settings) {
        return this.settings[name];
      }
      return null;
    }

    /**
     * Create colgroup col elements.
     *
     * @returns {DocumentFragment}
     */

  }, {
    key: 'createColGroupsCol',
    value: function createColGroupsCol() {
      var _this = this;

      var d = document;
      var fragment = d.createDocumentFragment();

      if (this.hot.hasRowHeaders()) {
        fragment.appendChild(this.createColElement(-1));
      }

      this.samples.forEach(function (sample) {
        (0, _array.arrayEach)(sample.strings, function (string) {
          fragment.appendChild(_this.createColElement(string.col));
        });
      });

      return fragment;
    }

    /**
     * Create table row element.
     *
     * @param {Number} row Row index.
     * @returns {DocumentFragment} Returns created table row elements.
     */

  }, {
    key: 'createRow',
    value: function createRow(row) {
      var _this2 = this;

      var d = document;
      var fragment = d.createDocumentFragment();
      var th = d.createElement('th');

      if (this.hot.hasRowHeaders()) {
        this.hot.view.appendRowHeader(row, th);

        fragment.appendChild(th);
      }

      this.samples.forEach(function (sample) {
        (0, _array.arrayEach)(sample.strings, function (string) {
          var column = string.col;
          var cellProperties = _this2.hot.getCellMeta(row, column);

          cellProperties.col = column;
          cellProperties.row = row;

          var renderer = _this2.hot.getCellRenderer(cellProperties);
          var td = d.createElement('td');

          renderer(_this2.hot, td, row, column, _this2.hot.colToProp(column), string.value, cellProperties);
          fragment.appendChild(td);
        });
      });

      return fragment;
    }
  }, {
    key: 'createColumnHeadersRow',
    value: function createColumnHeadersRow() {
      var _this3 = this;

      var d = document;
      var fragment = d.createDocumentFragment();

      if (this.hot.hasRowHeaders()) {
        var th = d.createElement('th');
        this.hot.view.appendColHeader(-1, th);
        fragment.appendChild(th);
      }

      this.samples.forEach(function (sample) {
        (0, _array.arrayEach)(sample.strings, function (string) {
          var column = string.col;

          var th = d.createElement('th');

          _this3.hot.view.appendColHeader(column, th);
          fragment.appendChild(th);
        });
      });

      return fragment;
    }

    /**
     * Create table column elements.
     *
     * @param {Number} column Column index.
     * @returns {DocumentFragment} Returns created column table column elements.
     */

  }, {
    key: 'createCol',
    value: function createCol(column) {
      var _this4 = this;

      var d = document;
      var fragment = d.createDocumentFragment();

      this.samples.forEach(function (sample) {
        (0, _array.arrayEach)(sample.strings, function (string) {
          var row = string.row;
          var cellProperties = _this4.hot.getCellMeta(row, column);

          cellProperties.col = column;
          cellProperties.row = row;

          var renderer = _this4.hot.getCellRenderer(cellProperties);
          var td = d.createElement('td');
          var tr = d.createElement('tr');

          renderer(_this4.hot, td, row, column, _this4.hot.colToProp(column), string.value, cellProperties);
          tr.appendChild(td);
          fragment.appendChild(tr);
        });
      });

      return fragment;
    }

    /**
     * Remove table from document and reset internal state.
     */

  }, {
    key: 'clean',
    value: function clean() {
      this.rows.length = 0;
      this.rows[-1] = void 0;
      this.columns.length = 0;

      if (this.samples) {
        this.samples.clear();
      }
      this.samples = null;
      this.removeTable();
    }

    /**
     * Inject generated table into document.
     *
     * @param {HTMLElement} [parent=null]
     */

  }, {
    key: 'injectTable',
    value: function injectTable() {
      var parent = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;

      if (!this.injected) {
        (parent || this.hot.rootElement).appendChild(this.container.fragment);
        this.injected = true;
      }
    }

    /**
     * Remove table from document.
     */

  }, {
    key: 'removeTable',
    value: function removeTable() {
      if (this.injected && this.container.container.parentNode) {
        this.container.container.parentNode.removeChild(this.container.container);
        this.container = null;
        this.injected = false;
      }
    }

    /**
     * Create col element.
     *
     * @param {Number} column Column index.
     * @returns {HTMLElement}
     */

  }, {
    key: 'createColElement',
    value: function createColElement(column) {
      var d = document;
      var col = d.createElement('col');

      col.style.width = this.hot.view.wt.wtTable.getStretchedColumnWidth(column) + 'px';

      return col;
    }

    /**
     * Create table element.
     *
     * @param {String} className
     * @returns {Object}
     */

  }, {
    key: 'createTable',
    value: function createTable() {
      var className = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '';

      var d = document;
      var fragment = d.createDocumentFragment();
      var table = d.createElement('table');
      var tHead = d.createElement('thead');
      var tBody = d.createElement('tbody');
      var colGroup = d.createElement('colgroup');
      var tr = d.createElement('tr');
      var th = d.createElement('th');

      if (this.isVertical()) {
        table.appendChild(colGroup);
      }
      if (this.isHorizontal()) {
        tr.appendChild(th);
        tHead.appendChild(tr);
        table.style.tableLayout = 'auto';
        table.style.width = 'auto';
      }
      table.appendChild(tHead);

      if (this.isVertical()) {
        tBody.appendChild(tr);
      }
      table.appendChild(tBody);
      (0, _element.addClass)(table, className);
      fragment.appendChild(table);

      return { fragment: fragment, table: table, tHead: tHead, tBody: tBody, colGroup: colGroup, tr: tr, th: th };
    }

    /**
     * Create container for tables.
     *
     * @param {String} className
     * @returns {Object}
     */

  }, {
    key: 'createContainer',
    value: function createContainer() {
      var className = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '';

      var d = document;
      var fragment = d.createDocumentFragment();
      var container = d.createElement('div');

      className = 'htGhostTable htAutoSize ' + className.trim();
      (0, _element.addClass)(container, className);
      fragment.appendChild(container);

      return { fragment: fragment, container: container };
    }

    /**
     * Checks if table is raised vertically (checking rows).
     *
     * @returns {Boolean}
     */

  }, {
    key: 'isVertical',
    value: function isVertical() {
      return !!(this.rows.length && !this.columns.length);
    }

    /**
     * Checks if table is raised horizontally (checking columns).
     *
     * @returns {Boolean}
     */

  }, {
    key: 'isHorizontal',
    value: function isHorizontal() {
      return !!(this.columns.length && !this.rows.length);
    }
  }]);

  return GhostTable;
}();

exports.default = GhostTable;

/***/ }),
/* 70 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";

var addToUnscopables = __webpack_require__(37);
var step = __webpack_require__(282);
var Iterators = __webpack_require__(46);
var toIObject = __webpack_require__(27);

// 22.1.3.4 Array.prototype.entries()
// 22.1.3.13 Array.prototype.keys()
// 22.1.3.29 Array.prototype.values()
// 22.1.3.30 Array.prototype[@@iterator]()
module.exports = __webpack_require__(281)(Array, 'Array', function (iterated, kind) {
  this._t = toIObject(iterated); // target
  this._i = 0;                   // next index
  this._k = kind;                // kind
// 22.1.5.2.1 %ArrayIteratorPrototype%.next()
}, function () {
  var O = this._t;
  var kind = this._k;
  var index = this._i++;
  if (!O || index >= O.length) {
    this._t = undefined;
    return step(1);
  }
  if (kind == 'keys') return step(0, index);
  if (kind == 'values') return step(0, O[index]);
  return step(0, [index, O[index]]);
}, 'values');

// argumentsList[@@iterator] is %ArrayProto_values% (9.4.4.6, 9.4.4.7)
Iterators.Arguments = Iterators.Array;

addToUnscopables('keys');
addToUnscopables('values');
addToUnscopables('entries');


/***/ }),
/* 71 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


exports.__esModule = true;

var _createClass = 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); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

var _coords = __webpack_require__(43);

var _coords2 = _interopRequireDefault(_coords);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

/**
 * A cell range is a set of exactly two CellCoords (that can be the same or different)
 *
 * @class CellRange
 */
var CellRange = function () {
  /**
   * @param {CellCoords} highlight Used to draw bold border around a cell where selection was
   *                                          started and to edit the cell when you press Enter
   * @param {CellCoords} from Usually the same as highlight, but in Excel there is distinction - one can change
   *                                     highlight within a selection
   * @param {CellCoords} to End selection
   */
  function CellRange(highlight, from, to) {
    _classCallCheck(this, CellRange);

    this.highlight = highlight;
    this.from = from;
    this.to = to;
  }

  /**
   * Checks if given coords are valid in context of a given Walkontable instance
   *
   * @param {Walkontable} wotInstance
   * @returns {Boolean}
   */


  _createClass(CellRange, [{
    key: 'isValid',
    value: function isValid(wotInstance) {
      return this.from.isValid(wotInstance) && this.to.isValid(wotInstance);
    }

    /**
     * Checks if this cell range is restricted to one cell
     *
     * @returns {Boolean}
     */

  }, {
    key: 'isSingle',
    value: function isSingle() {
      return this.from.row === this.to.row && this.from.col === this.to.col;
    }

    /**
     * Returns selected range height (in number of rows)
     *
     * @returns {Number}
     */

  }, {
    key: 'getHeight',
    value: function getHeight() {
      return Math.max(this.from.row, this.to.row) - Math.min(this.from.row, this.to.row) + 1;
    }

    /**
     * Returns selected range width (in number of columns)
     *
     * @returns {Number}
     */

  }, {
    key: 'getWidth',
    value: function getWidth() {
      return Math.max(this.from.col, this.to.col) - Math.min(this.from.col, this.to.col) + 1;
    }

    /**
     * Checks if given cell coords is within `from` and `to` cell coords of this range
     *
     * @param {CellCoords} cellCoords
     * @returns {Boolean}
     */

  }, {
    key: 'includes',
    value: function includes(cellCoords) {
      var row = cellCoords.row,
          col = cellCoords.col;

      var topLeft = this.getTopLeftCorner();
      var bottomRight = this.getBottomRightCorner();

      return topLeft.row <= row && bottomRight.row >= row && topLeft.col <= col && bottomRight.col >= col;
    }

    /**
     * Checks if given range is within of this range
     *
     * @param {CellRange} testedRange
     * @returns {Boolean}
     */

  }, {
    key: 'includesRange',
    value: function includesRange(testedRange) {
      return this.includes(testedRange.getTopLeftCorner()) && this.includes(testedRange.getBottomRightCorner());
    }

    /**
     * Checks if given range is equal to this range
     *
     * @param {CellRange} testedRange
     * @returns {Boolean}
     */

  }, {
    key: 'isEqual',
    value: function isEqual(testedRange) {
      return Math.min(this.from.row, this.to.row) == Math.min(testedRange.from.row, testedRange.to.row) && Math.max(this.from.row, this.to.row) == Math.max(testedRange.from.row, testedRange.to.row) && Math.min(this.from.col, this.to.col) == Math.min(testedRange.from.col, testedRange.to.col) && Math.max(this.from.col, this.to.col) == Math.max(testedRange.from.col, testedRange.to.col);
    }

    /**
     * Checks if tested range overlaps with the range.
     * Range A is considered to to be overlapping with range B if intersection of A and B or B and A is not empty.
     *
     * @param {CellRange} testedRange
     * @returns {Boolean}
     */

  }, {
    key: 'overlaps',
    value: function overlaps(testedRange) {
      return testedRange.isSouthEastOf(this.getTopLeftCorner()) && testedRange.isNorthWestOf(this.getBottomRightCorner());
    }

    /**
     * @param {CellRange} testedCoords
     * @returns {Boolean}
     */

  }, {
    key: 'isSouthEastOf',
    value: function isSouthEastOf(testedCoords) {
      return this.getTopLeftCorner().isSouthEastOf(testedCoords) || this.getBottomRightCorner().isSouthEastOf(testedCoords);
    }

    /**
     * @param {CellRange} testedCoords
     * @returns {Boolean}
     */

  }, {
    key: 'isNorthWestOf',
    value: function isNorthWestOf(testedCoords) {
      return this.getTopLeftCorner().isNorthWestOf(testedCoords) || this.getBottomRightCorner().isNorthWestOf(testedCoords);
    }

    /**
     * Adds a cell to a range (only if exceeds corners of the range). Returns information if range was expanded
     *
     * @param {CellCoords} cellCoords
     * @returns {Boolean}
     */

  }, {
    key: 'expand',
    value: function expand(cellCoords) {
      var topLeft = this.getTopLeftCorner();
      var bottomRight = this.getBottomRightCorner();

      if (cellCoords.row < topLeft.row || cellCoords.col < topLeft.col || cellCoords.row > bottomRight.row || cellCoords.col > bottomRight.col) {
        this.from = new _coords2.default(Math.min(topLeft.row, cellCoords.row), Math.min(topLeft.col, cellCoords.col));
        this.to = new _coords2.default(Math.max(bottomRight.row, cellCoords.row), Math.max(bottomRight.col, cellCoords.col));

        return true;
      }

      return false;
    }

    /**
     * @param {CellRange} expandingRange
     * @returns {Boolean}
     */

  }, {
    key: 'expandByRange',
    value: function expandByRange(expandingRange) {
      if (this.includesRange(expandingRange) || !this.overlaps(expandingRange)) {
        return false;
      }

      var topLeft = this.getTopLeftCorner();
      var bottomRight = this.getBottomRightCorner();
      var topRight = this.getTopRightCorner();
      var bottomLeft = this.getBottomLeftCorner();

      var expandingTopLeft = expandingRange.getTopLeftCorner();
      var expandingBottomRight = expandingRange.getBottomRightCorner();

      var resultTopRow = Math.min(topLeft.row, expandingTopLeft.row);
      var resultTopCol = Math.min(topLeft.col, expandingTopLeft.col);
      var resultBottomRow = Math.max(bottomRight.row, expandingBottomRight.row);
      var resultBottomCol = Math.max(bottomRight.col, expandingBottomRight.col);

      var finalFrom = new _coords2.default(resultTopRow, resultTopCol),
          finalTo = new _coords2.default(resultBottomRow, resultBottomCol);
      var isCorner = new CellRange(finalFrom, finalFrom, finalTo).isCorner(this.from, expandingRange),
          onlyMerge = expandingRange.isEqual(new CellRange(finalFrom, finalFrom, finalTo));

      if (isCorner && !onlyMerge) {
        if (this.from.col > finalFrom.col) {
          finalFrom.col = resultBottomCol;
          finalTo.col = resultTopCol;
        }
        if (this.from.row > finalFrom.row) {
          finalFrom.row = resultBottomRow;
          finalTo.row = resultTopRow;
        }
      }
      this.from = finalFrom;
      this.to = finalTo;

      return true;
    }

    /**
     * @returns {String}
     */

  }, {
    key: 'getDirection',
    value: function getDirection() {
      if (this.from.isNorthWestOf(this.to)) {
        // NorthWest - SouthEast
        return 'NW-SE';
      } else if (this.from.isNorthEastOf(this.to)) {
        // NorthEast - SouthWest
        return 'NE-SW';
      } else if (this.from.isSouthEastOf(this.to)) {
        // SouthEast - NorthWest
        return 'SE-NW';
      } else if (this.from.isSouthWestOf(this.to)) {
        // SouthWest - NorthEast
        return 'SW-NE';
      }
    }

    /**
     * @param {String} direction
     */

  }, {
    key: 'setDirection',
    value: function setDirection(direction) {
      switch (direction) {
        case 'NW-SE':
          var _ref = [this.getTopLeftCorner(), this.getBottomRightCorner()];
          this.from = _ref[0];
          this.to = _ref[1];

          break;
        case 'NE-SW':
          var _ref2 = [this.getTopRightCorner(), this.getBottomLeftCorner()];
          this.from = _ref2[0];
          this.to = _ref2[1];

          break;
        case 'SE-NW':
          var _ref3 = [this.getBottomRightCorner(), this.getTopLeftCorner()];
          this.from = _ref3[0];
          this.to = _ref3[1];

          break;
        case 'SW-NE':
          var _ref4 = [this.getBottomLeftCorner(), this.getTopRightCorner()];
          this.from = _ref4[0];
          this.to = _ref4[1];

          break;
        default:
          break;
      }
    }

    /**
     * Get top left corner of this range
     *
     * @returns {CellCoords}
     */

  }, {
    key: 'getTopLeftCorner',
    value: function getTopLeftCorner() {
      return new _coords2.default(Math.min(this.from.row, this.to.row), Math.min(this.from.col, this.to.col));
    }

    /**
     * Get bottom right corner of this range
     *
     * @returns {CellCoords}
     */

  }, {
    key: 'getBottomRightCorner',
    value: function getBottomRightCorner() {
      return new _coords2.default(Math.max(this.from.row, this.to.row), Math.max(this.from.col, this.to.col));
    }

    /**
     * Get top right corner of this range
     *
     * @returns {CellCoords}
     */

  }, {
    key: 'getTopRightCorner',
    value: function getTopRightCorner() {
      return new _coords2.default(Math.min(this.from.row, this.to.row), Math.max(this.from.col, this.to.col));
    }

    /**
     * Get bottom left corner of this range
     *
     * @returns {CellCoords}
     */

  }, {
    key: 'getBottomLeftCorner',
    value: function getBottomLeftCorner() {
      return new _coords2.default(Math.max(this.from.row, this.to.row), Math.min(this.from.col, this.to.col));
    }

    /**
     * @param {CellCoords} coords
     * @param {CellRange} expandedRange
     * @returns {*}
     */

  }, {
    key: 'isCorner',
    value: function isCorner(coords, expandedRange) {
      if (expandedRange) {
        if (expandedRange.includes(coords)) {
          if (this.getTopLeftCorner().isEqual(new _coords2.default(expandedRange.from.row, expandedRange.from.col)) || this.getTopRightCorner().isEqual(new _coords2.default(expandedRange.from.row, expandedRange.to.col)) || this.getBottomLeftCorner().isEqual(new _coords2.default(expandedRange.to.row, expandedRange.from.col)) || this.getBottomRightCorner().isEqual(new _coords2.default(expandedRange.to.row, expandedRange.to.col))) {
            return true;
          }
        }
      }

      return coords.isEqual(this.getTopLeftCorner()) || coords.isEqual(this.getTopRightCorner()) || coords.isEqual(this.getBottomLeftCorner()) || coords.isEqual(this.getBottomRightCorner());
    }

    /**
     * @param {CellCoords} coords
     * @param {CellRange} expandedRange
     * @returns {CellCoords}
     */

  }, {
    key: 'getOppositeCorner',
    value: function getOppositeCorner(coords, expandedRange) {
      if (!(coords instanceof _coords2.default)) {
        return false;
      }

      if (expandedRange) {
        if (expandedRange.includes(coords)) {
          if (this.getTopLeftCorner().isEqual(new _coords2.default(expandedRange.from.row, expandedRange.from.col))) {
            return this.getBottomRightCorner();
          }
          if (this.getTopRightCorner().isEqual(new _coords2.default(expandedRange.from.row, expandedRange.to.col))) {
            return this.getBottomLeftCorner();
          }
          if (this.getBottomLeftCorner().isEqual(new _coords2.default(expandedRange.to.row, expandedRange.from.col))) {
            return this.getTopRightCorner();
          }
          if (this.getBottomRightCorner().isEqual(new _coords2.default(expandedRange.to.row, expandedRange.to.col))) {
            return this.getTopLeftCorner();
          }
        }
      }

      if (coords.isEqual(this.getBottomRightCorner())) {
        return this.getTopLeftCorner();
      } else if (coords.isEqual(this.getTopLeftCorner())) {
        return this.getBottomRightCorner();
      } else if (coords.isEqual(this.getTopRightCorner())) {
        return this.getBottomLeftCorner();
      } else if (coords.isEqual(this.getBottomLeftCorner())) {
        return this.getTopRightCorner();
      }
    }

    /**
     * @param {CellRange} range
     * @returns {Array}
     */

  }, {
    key: 'getBordersSharedWith',
    value: function getBordersSharedWith(range) {
      if (!this.includesRange(range)) {
        return [];
      }

      var thisBorders = {
        top: Math.min(this.from.row, this.to.row),
        bottom: Math.max(this.from.row, this.to.row),
        left: Math.min(this.from.col, this.to.col),
        right: Math.max(this.from.col, this.to.col)
      };
      var rangeBorders = {
        top: Math.min(range.from.row, range.to.row),
        bottom: Math.max(range.from.row, range.to.row),
        left: Math.min(range.from.col, range.to.col),
        right: Math.max(range.from.col, range.to.col)
      };
      var result = [];

      if (thisBorders.top == rangeBorders.top) {
        result.push('top');
      }
      if (thisBorders.right == rangeBorders.right) {
        result.push('right');
      }
      if (thisBorders.bottom == rangeBorders.bottom) {
        result.push('bottom');
      }
      if (thisBorders.left == rangeBorders.left) {
        result.push('left');
      }

      return result;
    }

    /**
     * Get inner selected cell coords defined by this range
     *
     * @returns {Array}
     */

  }, {
    key: 'getInner',
    value: function getInner() {
      var topLeft = this.getTopLeftCorner();
      var bottomRight = this.getBottomRightCorner();
      var out = [];

      for (var r = topLeft.row; r <= bottomRight.row; r++) {
        for (var c = topLeft.col; c <= bottomRight.col; c++) {
          if (!(this.from.row === r && this.from.col === c) && !(this.to.row === r && this.to.col === c)) {
            out.push(new _coords2.default(r, c));
          }
        }
      }
      return out;
    }

    /**
     * Get all selected cell coords defined by this range
     *
     * @returns {Array}
     */

  }, {
    key: 'getAll',
    value: function getAll() {
      var topLeft = this.getTopLeftCorner();
      var bottomRight = this.getBottomRightCorner();
      var out = [];

      for (var r = topLeft.row; r <= bottomRight.row; r++) {
        for (var c = topLeft.col; c <= bottomRight.col; c++) {
          if (topLeft.row === r && topLeft.col === c) {
            out.push(topLeft);
          } else if (bottomRight.row === r && bottomRight.col === c) {
            out.push(bottomRight);
          } else {
            out.push(new _coords2.default(r, c));
          }
        }
      }

      return out;
    }

    /**
     * Runs a callback function against all cells in the range. You can break the iteration by returning
     * `false` in the callback function
     *
     * @param callback {Function}
     */

  }, {
    key: 'forAll',
    value: function forAll(callback) {
      var topLeft = this.getTopLeftCorner();
      var bottomRight = this.getBottomRightCorner();

      for (var r = topLeft.row; r <= bottomRight.row; r++) {
        for (var c = topLeft.col; c <= bottomRight.col; c++) {
          var breakIteration = callback(r, c);

          if (breakIteration === false) {
            return;
          }
        }
      }
    }
  }]);

  return CellRange;
}();

exports.default = CellRange;

/***/ }),
/* 72 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


exports.__esModule = true;
exports.ITEMS = exports.UNDO = exports.SEPARATOR = exports.ROW_BELOW = exports.ROW_ABOVE = exports.REMOVE_ROW = exports.REMOVE_COLUMN = exports.REDO = exports.READ_ONLY = exports.COLUMN_RIGHT = exports.COLUMN_LEFT = exports.CLEAR_COLUMN = exports.ALIGNMENT = undefined;

var _predefinedItems2;

var _alignment = __webpack_require__(344);

Object.defineProperty(exports, 'ALIGNMENT', {
  enumerable: true,
  get: function get() {
    return _alignment.KEY;
  }
});

var _clearColumn = __webpack_require__(345);

Object.defineProperty(exports, 'CLEAR_COLUMN', {
  enumerable: true,
  get: function get() {
    return _clearColumn.KEY;
  }
});

var _columnLeft = __webpack_require__(346);

Object.defineProperty(exports, 'COLUMN_LEFT', {
  enumerable: true,
  get: function get() {
    return _columnLeft.KEY;
  }
});

var _columnRight = __webpack_require__(347);

Object.defineProperty(exports, 'COLUMN_RIGHT', {
  enumerable: true,
  get: function get() {
    return _columnRight.KEY;
  }
});

var _readOnly = __webpack_require__(348);

Object.defineProperty(exports, 'READ_ONLY', {
  enumerable: true,
  get: function get() {
    return _readOnly.KEY;
  }
});

var _redo = __webpack_require__(349);

Object.defineProperty(exports, 'REDO', {
  enumerable: true,
  get: function get() {
    return _redo.KEY;
  }
});

var _removeColumn = __webpack_require__(350);

Object.defineProperty(exports, 'REMOVE_COLUMN', {
  enumerable: true,
  get: function get() {
    return _removeColumn.KEY;
  }
});

var _removeRow = __webpack_require__(351);

Object.defineProperty(exports, 'REMOVE_ROW', {
  enumerable: true,
  get: function get() {
    return _removeRow.KEY;
  }
});

var _rowAbove = __webpack_require__(352);

Object.defineProperty(exports, 'ROW_ABOVE', {
  enumerable: true,
  get: function get() {
    return _rowAbove.KEY;
  }
});

var _rowBelow = __webpack_require__(353);

Object.defineProperty(exports, 'ROW_BELOW', {
  enumerable: true,
  get: function get() {
    return _rowBelow.KEY;
  }
});

var _separator = __webpack_require__(73);

Object.defineProperty(exports, 'SEPARATOR', {
  enumerable: true,
  get: function get() {
    return _separator.KEY;
  }
});

var _undo = __webpack_require__(354);

Object.defineProperty(exports, 'UNDO', {
  enumerable: true,
  get: function get() {
    return _undo.KEY;
  }
});
exports.predefinedItems = predefinedItems;
exports.addItem = addItem;

var _object = __webpack_require__(3);

var _alignment2 = _interopRequireDefault(_alignment);

var _clearColumn2 = _interopRequireDefault(_clearColumn);

var _columnLeft2 = _interopRequireDefault(_columnLeft);

var _columnRight2 = _interopRequireDefault(_columnRight);

var _readOnly2 = _interopRequireDefault(_readOnly);

var _redo2 = _interopRequireDefault(_redo);

var _removeColumn2 = _interopRequireDefault(_removeColumn);

var _removeRow2 = _interopRequireDefault(_removeRow);

var _rowAbove2 = _interopRequireDefault(_rowAbove);

var _rowBelow2 = _interopRequireDefault(_rowBelow);

var _separator2 = _interopRequireDefault(_separator);

var _undo2 = _interopRequireDefault(_undo);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }

var ITEMS = exports.ITEMS = [_rowAbove.KEY, _rowBelow.KEY, _columnLeft.KEY, _columnRight.KEY, _clearColumn.KEY, _removeRow.KEY, _removeColumn.KEY, _undo.KEY, _redo.KEY, _readOnly.KEY, _alignment.KEY, _separator.KEY];

var _predefinedItems = (_predefinedItems2 = {}, _defineProperty(_predefinedItems2, _separator.KEY, _separator2.default), _defineProperty(_predefinedItems2, _rowAbove.KEY, _rowAbove2.default), _defineProperty(_predefinedItems2, _rowBelow.KEY, _rowBelow2.default), _defineProperty(_predefinedItems2, _columnLeft.KEY, _columnLeft2.default), _defineProperty(_predefinedItems2, _columnRight.KEY, _columnRight2.default), _defineProperty(_predefinedItems2, _clearColumn.KEY, _clearColumn2.default), _defineProperty(_predefinedItems2, _removeRow.KEY, _removeRow2.default), _defineProperty(_predefinedItems2, _removeColumn.KEY, _removeColumn2.default), _defineProperty(_predefinedItems2, _undo.KEY, _undo2.default), _defineProperty(_predefinedItems2, _redo.KEY, _redo2.default), _defineProperty(_predefinedItems2, _readOnly.KEY, _readOnly2.default), _defineProperty(_predefinedItems2, _alignment.KEY, _alignment2.default), _predefinedItems2);

/**
 * Gets new object with all predefined menu items.
 *
 * @returns {Object}
 */
function predefinedItems() {
  var items = {};

  (0, _object.objectEach)(_predefinedItems, function (itemFactory, key) {
    items[key] = itemFactory();
  });

  return items;
}

/**
 * Add new predefined menu item to the collection.
 *
 * @param {String} key Menu command id.
 * @param {Object} item Object command descriptor.
 */
function addItem(key, item) {
  if (ITEMS.indexOf(key) === -1) {
    _predefinedItems[key] = item;
  }
}

/***/ }),
/* 73 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


exports.__esModule = true;
exports.default = separatorItem;
var KEY = exports.KEY = '---------';

function separatorItem() {
  return {
    name: KEY
  };
}

/***/ }),
/* 74 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";

var $defineProperty = __webpack_require__(18);
var createDesc = __webpack_require__(49);

module.exports = function (object, index, value) {
  if (index in object) $defineProperty.f(object, index, createDesc(0, value));
  else object[index] = value;
};


/***/ }),
/* 75 */
/***/ (function(module, exports, __webpack_require__) {

var isObject = __webpack_require__(12);
var document = __webpack_require__(10).document;
// typeof document.createElement is 'object' in old IE
var is = isObject(document) && isObject(document.createElement);
module.exports = function (it) {
  return is ? document.createElement(it) : {};
};


/***/ }),
/* 76 */
/***/ (function(module, exports) {

// IE 8- don't enum bug keys
module.exports = (
  'constructor,hasOwnProperty,isPrototypeOf,propertyIsEnumerable,toLocaleString,toString,valueOf'
).split(',');


/***/ }),
/* 77 */
/***/ (function(module, exports, __webpack_require__) {

var MATCH = __webpack_require__(8)('match');
module.exports = function (KEY) {
  var re = /./;
  try {
    '/./'[KEY](re);
  } catch (e) {
    try {
      re[MATCH] = false;
      return !'/./'[KEY](re);
    } catch (f) { /* empty */ }
  } return true;
};


/***/ }),
/* 78 */
/***/ (function(module, exports, __webpack_require__) {

// fallback for non-array-like ES3 and non-enumerable old V8 strings
var cof = __webpack_require__(38);
// eslint-disable-next-line no-prototype-builtins
module.exports = Object('z').propertyIsEnumerable(0) ? Object : function (it) {
  return cof(it) == 'String' ? it.split('') : Object(it);
};


/***/ }),
/* 79 */
/***/ (function(module, exports, __webpack_require__) {

var ITERATOR = __webpack_require__(8)('iterator');
var SAFE_CLOSING = false;

try {
  var riter = [7][ITERATOR]();
  riter['return'] = function () { SAFE_CLOSING = true; };
  // eslint-disable-next-line no-throw-literal
  Array.from(riter, function () { throw 2; });
} catch (e) { /* empty */ }

module.exports = function (exec, skipClosing) {
  if (!skipClosing && !SAFE_CLOSING) return false;
  var safe = false;
  try {
    var arr = [7];
    var iter = arr[ITERATOR]();
    iter.next = function () { return { done: safe = true }; };
    arr[ITERATOR] = function () { return iter; };
    exec(arr);
  } catch (e) { /* empty */ }
  return safe;
};


/***/ }),
/* 80 */
/***/ (function(module, exports, __webpack_require__) {

// 19.1.2.2 / 15.2.3.5 Object.create(O [, Properties])
var anObject = __webpack_require__(17);
var dPs = __webpack_require__(399);
var enumBugKeys = __webpack_require__(76);
var IE_PROTO = __webpack_require__(83)('IE_PROTO');
var Empty = function () { /* empty */ };
var PROTOTYPE = 'prototype';

// Create object with fake `null` prototype: use iframe Object with cleared prototype
var createDict = function () {
  // Thrash, waste and sodomy: IE GC bug
  var iframe = __webpack_require__(75)('iframe');
  var i = enumBugKeys.length;
  var lt = '<';
  var gt = '>';
  var iframeDocument;
  iframe.style.display = 'none';
  __webpack_require__(274).appendChild(iframe);
  iframe.src = 'javascript:'; // eslint-disable-line no-script-url
  // createDict = iframe.contentWindow.Object;
  // html.removeChild(iframe);
  iframeDocument = iframe.contentWindow.document;
  iframeDocument.open();
  iframeDocument.write(lt + 'script' + gt + 'document.F=Object' + lt + '/script' + gt);
  iframeDocument.close();
  createDict = iframeDocument.F;
  while (i--) delete createDict[PROTOTYPE][enumBugKeys[i]];
  return createDict();
};

module.exports = Object.create || function create(O, Properties) {
  var result;
  if (O !== null) {
    Empty[PROTOTYPE] = anObject(O);
    result = new Empty();
    Empty[PROTOTYPE] = null;
    // add "__proto__" for Object.getPrototypeOf polyfill
    result[IE_PROTO] = O;
  } else result = createDict();
  return Properties === undefined ? result : dPs(result, Properties);
};


/***/ }),
/* 81 */
/***/ (function(module, exports, __webpack_require__) {

var pIE = __webpack_require__(48);
var createDesc = __webpack_require__(49);
var toIObject = __webpack_require__(27);
var toPrimitive = __webpack_require__(87);
var has = __webpack_require__(26);
var IE8_DOM_DEFINE = __webpack_require__(275);
var gOPD = Object.getOwnPropertyDescriptor;

exports.f = __webpack_require__(20) ? gOPD : function getOwnPropertyDescriptor(O, P) {
  O = toIObject(O);
  P = toPrimitive(P, true);
  if (IE8_DOM_DEFINE) try {
    return gOPD(O, P);
  } catch (e) { /* empty */ }
  if (has(O, P)) return createDesc(!pIE.f.call(O, P), O[P]);
};


/***/ }),
/* 82 */
/***/ (function(module, exports, __webpack_require__) {

// 19.1.2.7 / 15.2.3.4 Object.getOwnPropertyNames(O)
var $keys = __webpack_require__(285);
var hiddenKeys = __webpack_require__(76).concat('length', 'prototype');

exports.f = Object.getOwnPropertyNames || function getOwnPropertyNames(O) {
  return $keys(O, hiddenKeys);
};


/***/ }),
/* 83 */
/***/ (function(module, exports, __webpack_require__) {

var shared = __webpack_require__(84)('keys');
var uid = __webpack_require__(51);
module.exports = function (key) {
  return shared[key] || (shared[key] = uid(key));
};


/***/ }),
/* 84 */
/***/ (function(module, exports, __webpack_require__) {

var global = __webpack_require__(10);
var SHARED = '__core-js_shared__';
var store = global[SHARED] || (global[SHARED] = {});
module.exports = function (key) {
  return store[key] || (store[key] = {});
};


/***/ }),
/* 85 */
/***/ (function(module, exports, __webpack_require__) {

// helper for String#{startsWith, endsWith, includes}
var isRegExp = __webpack_require__(279);
var defined = __webpack_require__(33);

module.exports = function (that, searchString, NAME) {
  if (isRegExp(searchString)) throw TypeError('String#' + NAME + " doesn't accept regex!");
  return String(defined(that));
};


/***/ }),
/* 86 */
/***/ (function(module, exports, __webpack_require__) {

var ctx = __webpack_require__(30);
var invoke = __webpack_require__(396);
var html = __webpack_require__(274);
var cel = __webpack_require__(75);
var global = __webpack_require__(10);
var process = global.process;
var setTask = global.setImmediate;
var clearTask = global.clearImmediate;
var MessageChannel = global.MessageChannel;
var Dispatch = global.Dispatch;
var counter = 0;
var queue = {};
var ONREADYSTATECHANGE = 'onreadystatechange';
var defer, channel, port;
var run = function () {
  var id = +this;
  // eslint-disable-next-line no-prototype-builtins
  if (queue.hasOwnProperty(id)) {
    var fn = queue[id];
    delete queue[id];
    fn();
  }
};
var listener = function (event) {
  run.call(event.data);
};
// Node.js 0.9+ & IE10+ has setImmediate, otherwise:
if (!setTask || !clearTask) {
  setTask = function setImmediate(fn) {
    var args = [];
    var i = 1;
    while (arguments.length > i) args.push(arguments[i++]);
    queue[++counter] = function () {
      // eslint-disable-next-line no-new-func
      invoke(typeof fn == 'function' ? fn : Function(fn), args);
    };
    defer(counter);
    return counter;
  };
  clearTask = function clearImmediate(id) {
    delete queue[id];
  };
  // Node.js 0.8-
  if (__webpack_require__(38)(process) == 'process') {
    defer = function (id) {
      process.nextTick(ctx(run, id, 1));
    };
  // Sphere (JS game engine) Dispatch API
  } else if (Dispatch && Dispatch.now) {
    defer = function (id) {
      Dispatch.now(ctx(run, id, 1));
    };
  // Browsers with MessageChannel, includes WebWorkers
  } else if (MessageChannel) {
    channel = new MessageChannel();
    port = channel.port2;
    channel.port1.onmessage = listener;
    defer = ctx(port.postMessage, port, 1);
  // Browsers with postMessage, skip WebWorkers
  // IE8 has postMessage, but it's sync & typeof its postMessage is 'object'
  } else if (global.addEventListener && typeof postMessage == 'function' && !global.importScripts) {
    defer = function (id) {
      global.postMessage(id + '', '*');
    };
    global.addEventListener('message', listener, false);
  // IE8-
  } else if (ONREADYSTATECHANGE in cel('script')) {
    defer = function (id) {
      html.appendChild(cel('script'))[ONREADYSTATECHANGE] = function () {
        html.removeChild(this);
        run.call(id);
      };
    };
  // Rest old browsers
  } else {
    defer = function (id) {
      setTimeout(ctx(run, id, 1), 0);
    };
  }
}
module.exports = {
  set: setTask,
  clear: clearTask
};


/***/ }),
/* 87 */
/***/ (function(module, exports, __webpack_require__) {

// 7.1.1 ToPrimitive(input [, PreferredType])
var isObject = __webpack_require__(12);
// instead of the ES6 spec version, we didn't implement @@toPrimitive case
// and the second argument - flag - preferred type is a string
module.exports = function (it, S) {
  if (!isObject(it)) return it;
  var fn, val;
  if (S && typeof (fn = it.toString) == 'function' && !isObject(val = fn.call(it))) return val;
  if (typeof (fn = it.valueOf) == 'function' && !isObject(val = fn.call(it))) return val;
  if (!S && typeof (fn = it.toString) == 'function' && !isObject(val = fn.call(it))) return val;
  throw TypeError("Can't convert object to primitive value");
};


/***/ }),
/* 88 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


exports.__esModule = true;

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

var _mixed = __webpack_require__(23);

var _object = __webpack_require__(3);

/**
 * @alias Options
 * @constructor
 * @description

 * ## Constructor options
 *
 * Constructor options are applied using an object literal passed as a second argument to the Handsontable constructor.
 *
 * ```js
 * var hot = new Handsontable(document.getElementById('example1'), {
 *   data: myArray,
 *   width: 400,
 *   height: 300
 * });
 * ```
 *
 * ---
 * ## Cascading configuration
 *
 * Handsontable 0.9 and newer is using *Cascading Configuration*, which is a fast way to provide configuration options
 * for the entire table, including its columns and particular cells.
 *
 * Consider the following example:
 * ```js
 * var hot = new Handsontable(document.getElementById('example'), {
 *   readOnly: true,
 *   columns: [
 *     {readOnly: false},
 *     {},
 *     {}
 *   ],
 *   cells: function (row, col, prop) {
 *     var cellProperties = {};
 *
 *     if (row === 0 && col === 0) {
 *       cellProperties.readOnly = true;
 *     }
 *
 *     return cellProperties;
 *   }
 * });
 * ```
 *
 * The above notation will result in all TDs being *read only*, except for first column TDs which will be *editable*, except for the TD in top left corner which will still be *read only*.
 *
 * ### The Cascading Configuration model
 *
 * ##### 1. Constructor
 *
 * Configuration options that are provided using first-level `handsontable(container, {option: "value"})` and `updateSettings` method.
 *
 * ##### 2. Columns
 *
 * Configuration options that are provided using second-level object `handsontable(container, {columns: {option: "value"}]})`
 *
 * ##### 3. Cells
 *
 * Configuration options that are provided using third-level function `handsontable(container, {cells: function: (row, col, prop){ }})`
 *
 * ---
 * ## Architecture performance
 *
 * The Cascading Configuration model is based on prototypical inheritance. It is much faster and memory efficient compared
 * to the previous model that used jQuery extend. See: [http://jsperf.com/extending-settings](http://jsperf.com/extending-settings).
 *
 * ---
 * __Important notice:__ In order for the data separation to work properly, make sure that each instance of Handsontable has a unique `id`.
 */
function DefaultSettings() {};

DefaultSettings.prototype = {
  /**
   * License key for commercial version of Handsontable.
   *
   * @pro
   * @type {String}
   * @default 'trial'
   */
  licenseKey: 'trial',

  /**
   * @description
   * Initial data source that will be bound to the data grid __by reference__ (editing data grid alters the data source).
   * Can be declared as an Array of Arrays, Array of Objects or a Function.
   *
   * See [Understanding binding as reference](http://docs.handsontable.com/tutorial-data-binding.html#page-reference).
   *
   * @type {Array|Function}
   * @default undefined
   */
  data: void 0,

  /**
   * @description
   * Defines the structure of a new row when data source is an array of objects.
   *
   * See [data-schema](http://docs.handsontable.com/tutorial-data-sources.html#page-data-schema) for examples.
   *
   * @type {Object}
   * @default undefined
   */
  dataSchema: void 0,

  /**
   * Width of the grid. Can be a value or a function that returns a value.
   *
   * @type {Number|Function}
   * @default undefined
   */
  width: void 0,

  /**
   * Height of the grid. Can be a number or a function that returns a number.
   *
   * @type {Number|Function}
   * @default undefined
   */
  height: void 0,

  /**
   * @description
   * Initial number of rows.
   *
   * __Notice:__ This option only has effect in Handsontable constructor and only if `data` option is not provided
   *
   * @type {Number}
   * @default 5
   */
  startRows: 5,

  /**
   * @description
   * Initial number of columns.
   *
   * __Notice:__ This option only has effect in Handsontable constructor and only if `data` option is not provided
   *
   * @type {Number}
   * @default 5
   */
  startCols: 5,

  /**
   * Setting `true` or `false` will enable or disable the default row headers (1, 2, 3).
   * You can also define an array `['One', 'Two', 'Three', ...]` or a function to define the headers.
   * If a function is set the index of the row is passed as a parameter.
   *
   * @type {Boolean|Array|Function}
   * @default null
   * @example
   * ```js
   * ...
   * // as boolean
   * rowHeaders: true,
   * ...
   *
   * ...
   * // as array
   * rowHeaders: [1, 2, 3],
   * ...
   *
   * ...
   * // as function
   * rowHeaders: function(index) {
   *   return index + ': AB';
   * },
   * ...
   * ```
   */
  rowHeaders: void 0,

  /**
   * Setting `true` or `false` will enable or disable the default column headers (A, B, C).
   * You can also define an array `['One', 'Two', 'Three', ...]` or a function to define the headers.
   * If a function is set, then the index of the column is passed as a parameter.
   *
   * @type {Boolean|Array|Function}
   * @default null
   * @example
   * ```js
   * ...
   * // as boolean
   * colHeaders: true,
   * ...
   *
   * ...
   * // as array
   * colHeaders: ['A', 'B', 'C'],
   * ...
   *
   * ...
   * // as function
   * colHeaders: function(index) {
   *   return index + ': AB';
   * },
   * ...
   * ```
   */
  colHeaders: null,

  /**
   * Defines column widths in pixels. Accepts number, string (that will be converted to a number),
   * array of numbers (if you want to define column width separately for each column) or a
   * function (if you want to set column width dynamically on each render).
   *
   * @type {Array|Function|Number|String}
   * @default undefined
   * @example
   * ```js
   * ...
   * // as numeric, for each column.
   * colWidths: 100,
   * ...
   *
   * * ...
   * // as string, for each column.
   * colWidths: '100px',
   * ...
   *
   * ...
   * // as array, based on visual indexes. The rest of the columns have a default width.
   * colWidths: [100, 120, 90],
   * ...
   *
   * ...
   * // as function, based on visual indexes.
   * colWidths: function(index) {
   *   return index * 10;
   * },
   * ...
   * ```
   */
  colWidths: void 0,

  /**
   * Defines row heights in pixels. Accepts numbers, strings (that will be converted into a number),
   * array of numbers (if you want to define row height separately for each row) or a
   * function (if you want to set row height dynamically on each render).
   * If the ManualRowResize or AutoRowSize plugins are enabled, this is also the minimum height that can be set
   * via either of those two plugins.
   * Height should be equal or greater than 23px. Table is rendered incorrectly if height is less than 23px.
   *
   * @type {Array|Function|Number|String}
   * @default undefined
   * @example
   * ```js
   * ...
   * // as numeric, for each row.
   * rowHeights: 100,
   * ...
   *
   * * ...
   * // as string, for each row.
   * rowHeights: '100px',
   * ...
   *
   * ...
   * // as array, based on visual indexes. The rest of the rows have a default height.
   * rowHeights: [100, 120, 90],
   * ...
   *
   * ...
   * // as function, based on visual indexes.
   * rowHeights: function(index) {
   *   return index * 10;
   * },
   * ...
   * ```
   */
  rowHeights: void 0,

  /**
   * @description
   * Defines the cell properties and data binding for certain columns.
   *
   * __Notice:__ Using this option sets a fixed number of columns (options `startCols`, `minCols`, `maxCols` will be ignored).
   *
   * See [documentation -> datasources.html](http://docs.handsontable.com/tutorial-data-sources.html#page-nested) for examples.
   *
   * @type {Array|Function}
   * @default undefined
   * @example
   * ```js
   * ...
   * // as an array of objects. Order of the objects in array is representation of physical indexes.
   * columns: [
   *   {
   *     // column options for the first column
   *     type: 'numeric',
   *     format: '0,0.00 $'
   *   },
   *   {
   *     // column options for the second column
   *     type: 'text',
   *     readOnly: true
   *   }
   * ],
   * ...
   *
   * // or as function, based on physical indexes
   * ...
   * columns: function(index) {
  *    return {
  *      type: index > 0 ? 'numeric' : 'text',
  *      readOnly: index < 1
  *    }
   * }
   * ...
   * ```
   */
  columns: void 0,

  /**
   * @description
   * Defines the cell properties for given `row`, `col`, `prop` coordinates.
   * Any constructor or column option may be overwritten for a particular cell (row/column combination)
   * using the `cells` property in the Handsontable constructor.
   *
   * __Note:__ Parameters `row` and `col` always represent __physical indexes__. Example below show how to execute
   * operations based on the __visual__ representation of Handsontable.
   *
   * Possible values of `prop`:
   * - property name for column's data source object, when dataset is an [array of objects](/tutorial-data-sources.html#page-object)
   * - the same number as `col`, when dataset is an [array of arrays](/tutorial-data-sources.html#page-array)
   *
   * @type {Function}
   * @default undefined
   * @example
   * ```js
   * ...
   * cells: function (row, col, prop) {
   *   var cellProperties = {};
   *   var visualRowIndex = this.instance.toVisualRow(row);
   *   var visualColIndex = this.instance.toVisualColumn(col);
   *
   *   if (visualRowIndex === 0 && visualColIndex === 0) {
   *     cellProperties.readOnly = true;
   *   }
   *
   *   return cellProperties;
   * },
   * ...
   * ```
   */
  cells: void 0,

  /**
   * Any constructor or column option may be overwritten for a particular cell (row/column combination), using `cell`
   * array passed to the Handsontable constructor.
   *
   * @type {Array}
   * @default []
   * @example
   * ```js
   * ...
   * cell: [
   *   {row: 0, col: 0, readOnly: true}
   * ],
   * ...
   * ```
   */
  cell: [],

  /**
   * @description
   * If `true`, enables the {@link Comments} plugin, which enables an option to apply cell comments through the context menu
   * (configurable with context menu keys `commentsAddEdit`, `commentsRemove`).
   *
   * To initialize Handsontable with predefined comments, provide cell coordinates and comment text values in a form of an array.
   *
   * See [Comments](http://docs.handsontable.com/demo-comments_.html) demo for examples.
   *
   * @since 0.11.0
   * @type {Boolean|Array}
   * @default false
   * @example
   * ```js
   * ...
   * comments: [{row: 1, col: 1, comment: {value: "Test comment"}}],
   * ...
   * ```
   */
  comments: false,

  /**
   * @description
   * If `true`, enables the Custom Borders plugin, which enables an option to apply custom borders through the context menu (configurable with context menu key `borders`).
   *
   * To initialize Handsontable with predefined custom borders, provide cell coordinates and border styles in a form of an array.
   *
   * See [Custom Borders](http://docs.handsontable.com/demo-custom-borders.html) demo for examples.
   *
   * @since 0.11.0
   * @type {Boolean|Array}
   * @default false
   * @example
   * ```js
   * ...
   * customBorders: [
   *   {range: {
   *     from: {row: 1, col: 1},
   *     to: {row: 3, col: 4}},
   *     left: {},
   *     right: {},
   *     top: {},
   *     bottom: {}
   *   }
   * ],
   * ...
   *
   * // or
   * ...
   * customBorders: [
   *   {row: 2, col: 2, left: {width: 2, color: 'red'},
   *     right: {width: 1, color: 'green'}, top: '', bottom: ''}
   * ],
   * ...
   * ```
   */
  customBorders: false,

  /**
   * Minimum number of rows. At least that number of rows will be created during initialization.
   *
   * @type {Number}
   * @default 0
   */
  minRows: 0,

  /**
   * Minimum number of columns. At least that number of columns will be created during initialization.
   *
   * @type {Number}
   * @default 0
   */
  minCols: 0,

  /**
   * Maximum number of rows. If set to a value lower than the initial row count, the data will be trimmed to the provided value as the number of rows.
   *
   * @type {Number}
   * @default Infinity
   */
  maxRows: Infinity,

  /**
   * Maximum number of cols. If set to a value lower than the initial col count, the data will be trimmed to the provided value as the number of cols.
   *
   * @type {Number}
   * @default Infinity
   */
  maxCols: Infinity,

  /**
   * When set to 1 (or more), Handsontable will add a new row at the end of grid if there are no more empty rows.
   * (unless the number of rows exceeds the one set in the `maxRows` property)
   *
   * @type {Number}
   * @default 0
   */
  minSpareRows: 0,

  /**
   * When set to 1 (or more), Handsontable will add a new column at the end of grid if there are no more empty columns.
   * (unless the number of rows exceeds the one set in the `maxCols` property)
   *
   * @type {Number}
   * @default 0
   */
  minSpareCols: 0,

  /**
   * If set to `false`, there won't be an option to insert new rows in the Context Menu.
   *
   * @type {Boolean}
   * @default true
   */
  allowInsertRow: true,

  /**
   * If set to `false`, there won't be an option to insert new columns in the Context Menu.
   *
   * @type {Boolean}
   * @default true
   */
  allowInsertColumn: true,

  /**
   * If set to `false`, there won't be an option to remove rows in the Context Menu.
   *
   * @type {Boolean}
   * @default true
   */
  allowRemoveRow: true,

  /**
   * If set to `false`, there won't be an option to remove columns in the Context Menu.
   *
   * @type {Boolean}
   * @default true
   */
  allowRemoveColumn: true,

  /**
   * If true, selection of multiple cells using keyboard or mouse is allowed.
   *
   * @type {Boolean}
   * @default true
   */
  multiSelect: true,

  /**
   * Enables the fill handle (drag-down and copy-down) functionality, which shows a small rectangle in bottom
   * right corner of the selected area, that let's you expand values to the adjacent cells.
   *
   * Possible values: `true` (to enable in all directions), `'vertical'` or `'horizontal'` (to enable in one direction),
   * `false` (to disable completely). Setting to `true` enables the fillHandle plugin.
   *
   * Since 0.23.0 you can pass object to plugin which allows you to add more options for this functionality. If `autoInsertRow`
   * option is `true`, fill-handler will create new rows till it reaches the last row. It is enabled by default.
   *
   * @example
   * ```js
   * ...
   * fillHandle: true // enable plugin in all directions and with autoInsertRow as true
   * ...
   * // or
   * ...
   * fillHandle: 'vertical' // enable plugin in vertical direction and with autoInsertRow as true
   * ...
   * // or
   * ...
   * fillHandle: { // enable plugin in both directions and with autoInsertRow as false
   *   autoInsertRow: false,
   * }
   * // or
   * ...
   * fillHandle: { // enable plugin in vertical direction and with autoInsertRow as false
   *   autoInsertRow: false,
   *   direction: 'vertical' // 'vertical' or 'horizontal'
   * }
   * ```
   *
   * @type {Boolean|String|Object}
   * @default true
   */
  fillHandle: true,

  /**
   * Allows to specify the number of fixed (or *frozen*) rows at the top of the table.
   *
   * @type {Number}
   * @default 0
   * @example
   * ```js
   * fixedRowsTop: 3 // This would freeze the top 3 rows of the table.
   * ```
   */
  fixedRowsTop: 0,

  /**
   * Allows to specify the number of fixed (or *frozen*) rows at the bottom of the table.
   *
   * @pro
   * @type {Number}
   * @default 0
   * @example
   * ```js
   * fixedRowsBottom: 3 // This would freeze the top 3 rows of the table.
   * ```
   */
  fixedRowsBottom: 0,

  /**
   * Allows to specify the number of fixed (or *frozen*) columns on the left of the table.
   *
   * @type {Number}
   * @default 0
   * @example
   * ```js
   * fixedColumnsLeft: 3 // This would freeze the top 3 rows of the table.
   * ```
   */
  fixedColumnsLeft: 0,

  /**
   * If `true`, mouse click outside the grid will deselect the current selection.
   * Can be a function that takes the click event target and returns a boolean.
   *
   * @type {Boolean|Function}
   * @default true
   */
  outsideClickDeselects: true,

  /**
   * If `true`, <kbd>ENTER</kbd> begins editing mode (like in Google Docs). If `false`, <kbd>ENTER</kbd> moves to next
   * row (like Excel) and adds a new row if necessary. <kbd>TAB</kbd> adds new column if necessary.
   *
   * @type {Boolean}
   * @default true
   */
  enterBeginsEditing: true,

  /**
   * Defines the cursor movement after <kbd>ENTER</kbd> was pressed (<kbd>SHIFT</kbd> + <kbd>ENTER</kbd> uses a negative vector).
   * Can be an object or a function that returns an object. The event argument passed to the function
   * is a DOM Event object received after the <kbd>ENTER</kbd> key has been pressed. This event object can be used to check
   * whether user pressed <kbd>ENTER</kbd> or <kbd>SHIFT</kbd> + <kbd>ENTER</kbd>.
   *
   * @type {Object|Function}
   * @default {row: 1, col: 0}
   */
  enterMoves: { row: 1, col: 0 },

  /**
   * Defines the cursor movement after <kbd>TAB</kbd> is pressed (<kbd>SHIFT</kbd> + <kbd>TAB</kbd> uses a negative vector).
   * Can be an object or a function that returns an object. The event argument passed to the function
   * is a DOM Event object received after the <kbd>TAB</kbd> key has been pressed. This event object can be used to check
   * whether user pressed <kbd>TAB</kbd> or <kbd>SHIFT</kbd> + <kbd>TAB</kbd>.
   *
   * @type {Object}
   * @default {row: 0, col: 1}
   */
  tabMoves: { row: 0, col: 1 },

  /**
   * If `true`, pressing <kbd>TAB</kbd> or right arrow in the last column will move to first column in next row.
   *
   * @type {Boolean}
   * @default false
   */
  autoWrapRow: false,

  /**
   * If `true`, pressing <kbd>ENTER</kbd> or down arrow in the last row will move to the first row in the next column.
   *
   * @type {Boolean}
   * @default false
   */
  autoWrapCol: false,

  /**
   * @description
   * Turns on saving the state of column sorting, column positions and column sizes in local storage.
   *
   * You can save any sort of data in local storage to preserve table state between page reloads.
   * In order to enable data storage mechanism, `persistentState` option must be set to `true` (you can set it
   * either during Handsontable initialization or using the `updateSettings` method). When `persistentState` is enabled it exposes 3 hooks:
   *
   * __persistentStateSave__ (key: String, value: Mixed)
   *
   *   * Saves value under given key in browser local storage.
   *
   * __persistentStateLoad__ (key: String, valuePlaceholder: Object)
   *
   *   * Loads `value`, saved under given key, form browser local storage. The loaded `value` will be saved in `valuePlaceholder.value`
   *     (this is due to specific behaviour of `Hooks.run()` method). If no value have been saved under key `valuePlaceholder.value`
   *     will be `undefined`.
   *
   * __persistentStateReset__ (key: String)
   *
   *   * Clears the value saved under `key`. If no `key` is given, all values associated with table will be cleared.
   *
   * __Note:__ The main reason behind using `persistentState` hooks rather than regular LocalStorage API is that it
   * ensures separation of data stored by multiple Handsontable instances. In other words, if you have two (or more)
   * instances of Handsontable on one page, data saved by one instance won't be accessible by the second instance.
   * Those two instances can store data under the same key and no data would be overwritten.
   *
   * __Important:__ In order for the data separation to work properly, make sure that each instance of Handsontable has a unique `id`.
   *
   * @type {Boolean}
   * @default false
   */
  persistentState: void 0,

  /**
   * Class name for all visible rows in the current selection.
   *
   * @type {String}
   * @default undefined
   * @example
   * ```js
   * currentRowClassName: 'currentRow' // This will add a 'currentRow' class name to appropriate table cells.
   * ```
   */
  currentRowClassName: void 0,

  /**
   * Class name for all visible columns in the current selection.
   *
   * @type {String}
   * @default undefined
   * @example
   * ```js
   * currentColClassName: 'currentColumn' // This will add a 'currentColumn' class name to appropriate table cells.
   * ```
   */
  currentColClassName: void 0,

  /**
   * Class name for all visible headers in current selection.
   *
   * @type {String}
   * @since 0.27.0
   * @default 'ht__highlight'
   * @example
   * ```js
   * currentHeaderClassName: 'ht__highlight' // This will add a 'ht__highlight' class name to appropriate table headers.
   * ```
   */
  currentHeaderClassName: 'ht__highlight',
  /**
   * Class name for the Handsontable container element.
   *
   * @type {String|Array}
   * @default undefined
   */
  className: void 0,

  /**
   * Class name for all tables inside container element.
   *
   * @since 0.17.0
   * @type {String|Array}
   * @default undefined
   */
  tableClassName: void 0,

  /**
   * @description
   * Defines how the columns react, when the declared table width is different than the calculated sum of all column widths.
   * [See more](http://docs.handsontable.com/demo-stretching.html) mode. Possible values:
   *  * `'none'` Disable stretching
   *  * `'last'` Stretch only the last column
   *  * `'all'` Stretch all the columns evenly
   *
   * @type {String}
   * @default 'none'
   */
  stretchH: 'none',

  /**
   * Lets you overwrite the default `isEmptyRow` method, which checks if row at the provided index is empty.
   *
   * @type {Function}
   * @param {Number} row Visual row index.
   * @returns {Boolean}
   */
  isEmptyRow: function isEmptyRow(row) {
    var col, colLen, value, meta;

    for (col = 0, colLen = this.countCols(); col < colLen; col++) {
      value = this.getDataAtCell(row, col);

      if (value !== '' && value !== null && (0, _mixed.isDefined)(value)) {
        if ((typeof value === 'undefined' ? 'undefined' : _typeof(value)) === 'object') {
          meta = this.getCellMeta(row, col);

          return (0, _object.isObjectEquals)(this.getSchema()[meta.prop], value);
        }
        return false;
      }
    }

    return true;
  },


  /**
   * Lets you overwrite the default `isEmptyCol` method, which checks if column at the provided index is empty.
   *
   * @type {Function}
   * @param {Number} col Visual column index
   * @returns {Boolean}
   */
  isEmptyCol: function isEmptyCol(col) {
    var row, rowLen, value;

    for (row = 0, rowLen = this.countRows(); row < rowLen; row++) {
      value = this.getDataAtCell(row, col);

      if (value !== '' && value !== null && (0, _mixed.isDefined)(value)) {
        return false;
      }
    }

    return true;
  },


  /**
   * When set to `true`, the table is re-rendered when it is detected that it was made visible in DOM.
   *
   * @type {Boolean}
   * @default true
   */
  observeDOMVisibility: true,

  /**
   * If set to `true`, Handsontable will accept values that were marked as invalid by the cell `validator`.
   * It will result with *invalid* cells being treated as *valid* (will save the *invalid* value into the Handsontable data source).
   * If set to `false`, Handsontable will *not* accept the invalid values and won't allow the user to close the editor.
   * This option will be particularly useful when used with the Autocomplete's `strict` mode.
   *
   * @type {Boolean}
   * @default true
   * @since 0.9.5
   */
  allowInvalid: true,

  /**
   * If set to `true`, Handsontable will accept values that are empty (`null`, `undefined` or `''`).
   * If set to `false`, Handsontable will *not* accept the empty values and mark cell as invalid.
   *
   * @example
   * ```js
   * ...
   * allowEmpty: true // allow empty values for all cells (whole table)
   * ...
   * // or
   * ...
   * columns: [
   *   // allow empty values only for 'date' column
   *   {data: 'date', dateFormat: 'DD/MM/YYYY', allowEmpty: true}
   * ]
   * ...
   * ```
   *
   * @type {Boolean}
   * @default true
   * @since 0.23.0
   */
  allowEmpty: true,

  /**
   * CSS class name for cells that did not pass validation.
   *
   * @type {String}
   * @default 'htInvalid'
   */
  invalidCellClassName: 'htInvalid',

  /**
   * When set to an non-empty string, displayed as the cell content for empty cells. If a value of a different type is provided,
   * it will be stringified and applied as a string.
   *
   * @type {Mixed}
   * @default false
   */
  placeholder: false,

  /**
   * CSS class name for cells that have a placeholder in use.
   *
   * @type {String}
   * @default 'htPlaceholder'
   */
  placeholderCellClassName: 'htPlaceholder',

  /**
   * CSS class name for read-only cells.
   *
   * @type {String}
   * @default 'htDimmed'
   */
  readOnlyCellClassName: 'htDimmed',

  /**
   * @description
   * If a string is provided, it may be one of the following predefined values:
   * * `autocomplete`,
   * * `checkbox`,
   * * `html`,
   * * `numeric`,
   * * `password`.
   * * `text`.
   *
   * Or you can [register](http://docs.handsontable.com/demo-custom-renderers.html) the custom renderer under specified name and use
   * its name as an alias in your configuration.
   *
   * If a function is provided, it will receive the following arguments:
   * ```js
   * function(instance, TD, row, col, prop, value, cellProperties) {}
   * ```
   *
   * You can read more about custom renderes [in the documentation](http://docs.handsontable.com/demo-custom-renderers.html).
   *
   * @example
   * ```js
   * ...
   * Handsontable.renderers.registerRenderer('my.renderer', function(instance, TD, row, col, prop, value, cellProperties) {
   *   TD.innerHTML = value;
   * });
   * ...
   * columns: [
   *   {
   *     editor: 'select',
   *     renderer: 'autocomplete' // as string
   *   },
   *   {
   *     renderer: 'my.renderer' // custom renderer as an alias
   *   },
   *   {
   *     // renderer as custom function
   *     renderer: function(hotInstance, TD, row, col, prop, value, cellProperties) {
   *       TD.style.color = 'blue';
   *       TD.innerHTML = value;
   *     }
   *   }
   * ]
   * ...
   * ```
   *
   * @type {String|Function}
   * @default undefined
   */
  renderer: void 0,

  /**
   * CSS class name added to the commented cells.
   *
   * @type {String}
   * @default 'htCommentCell'
   */
  commentedCellClassName: 'htCommentCell',

  /**
   * If set to `true`, it enables the browser's native selection of a fragment of the text within a single cell, between adjacent cells or in a whole table.
   * If set to `'cell'`, it enables the possibility of selecting a fragment of the text within a single cell's body.
   *
   * @type {Boolean|String}
   * @default false
   */
  fragmentSelection: false,

  /**
   * @description
   * Make cell [read only](http://docs.handsontable.com/demo-read-only.html).
   *
   * @type {Boolean}
   * @default false
   */
  readOnly: false,

  /**
   * @description
   * When added to a `column` property, it skips the column on paste and pastes the data on the next column to the right.
   *
   * @type {Boolean}
   * @default false
   */
  skipColumnOnPaste: false,

  /**
   * @description
   * Setting to true enables the search plugin (see [demo](http://docs.handsontable.com/demo-search-for-values.html)).
   *
   * @type {Boolean}
   * @default false
   */
  search: false,

  /**
   * @description
   * Shortcut to define the combination of the cell renderer, editor and validator for the column, cell or whole table.
   *
   * Possible values:
   *  * [autocomplete](http://docs.handsontable.com/demo-autocomplete.html)
   *  * [checkbox](http://docs.handsontable.com/demo-checkbox.html)
   *  * [date](http://docs.handsontable.com/demo-date.html)
   *  * [dropdown](http://docs.handsontable.com/demo-dropdown.html)
   *  * [handsontable](http://docs.handsontable.com/demo-handsontable.html)
   *  * [numeric](http://docs.handsontable.com/demo-numeric.html)
   *  * [password](http://docs.handsontable.com/demo-password.html)
   *  * text
   *  * [time](http://docs.handsontable.com/demo-time.html)
   *
   * Or you can register the custom cell type under specified name and use
   * its name as an alias in your configuration.
   *
   * @example
   * ```js
   * ...
   * Handsontable.cellTypes.registerCellType('my.type', {
   *   editor: MyEditorClass,
   *   renderer: function(hot, td, row, col, prop, value, cellProperties) {
   *     td.innerHTML = value;
   *   },
   *   validator: function(value, callback) {
   *     callback(value === 'foo' ? true : false);
   *   }
   * });
   * ...
   * columns: [
   *   {
   *     type: 'text'
   *   },
   *   {
   *     type: 'my.type' // an alias to custom type
   *   },
   *   {
   *     type: 'checkbox'
   *   }
   * ]
   * ...
   * ```
   *
   * @type {String}
   * @default 'text'
   */
  type: 'text',

  /**
   * @description
   * Make cell copyable (pressing <kbd>CTRL</kbd> + <kbd>C</kbd> on your keyboard moves its value to system clipboard).
   *
   * __Note:__ this setting is `false` by default for cells with type `password`.
   *
   * @type {Boolean}
   * @default true
   * @since 0.10.2
   */
  copyable: true,

  /**
   * Defines the editor for the table/column/cell.
   *
   * If a string is provided, it may be one of the following predefined values:
   *  * [autocomplete](http://docs.handsontable.com/demo-autocomplete.html)
   *  * [checkbox](http://docs.handsontable.com/demo-checkbox.html)
   *  * [date](http://docs.handsontable.com/demo-date.html)
   *  * [dropdown](http://docs.handsontable.com/demo-dropdown.html)
   *  * [handsontable](http://docs.handsontable.com/demo-handsontable.html)
   *  * [mobile](http://docs.handsontable.com/demo-mobiles-and-tablets.html)
   *  * [password](http://docs.handsontable.com/demo-password.html)
   *  * [select](http://docs.handsontable.com/demo-select.html)
   *  * text
   *
   * Or you can [register](http://docs.handsontable.com/tutorial-cell-editor.html#registering-an-editor) the custom editor under specified name and use
   * its name as an alias in your configuration.
   *
   * To disable cell editing completely set `editor` property to `false`.
   *
   * @example
   * ```js
   * ...
   * columns: [
   *   {
   *     editor: 'select'
   *   },
   *   {
   *     editor: false
   *   }
   * ]
   * ...
   * ```
   *
   * @type {String|Function|Boolean}
   * @default 'text'
   */
  editor: void 0,

  /**
   * @description
   * Autocomplete definitions. See [autocomplete demo](http://docs.handsontable.com/demo-autocomplete.html) for examples and definitions.
   *
   * @type {Array}
   * @default undefined
   */
  autoComplete: void 0,

  /**
   * Control number of choices for the autocomplete (or dropdown) typed cells. After exceeding it, a scrollbar for the dropdown list of choices will appear.
   *
   * @since 0.18.0
   * @type {Number}
   * @default 10
   */
  visibleRows: 10,

  /**
   * Makes autocomplete or dropdown width the same as the edited cell width. If `false` then editor will be scaled
   * according to its content.
   *
   * @since 0.17.0
   * @type {Boolean}
   * @default true
   */
  trimDropdown: true,

  /**
   * Setting to true enables the debug mode, currently used to test the correctness of the row and column
   * header fixed positioning on a layer above the master table.
   *
   * @type {Boolean}
   * @default false
   */
  debug: false,

  /**
   * When set to `true`, the text of the cell content is wrapped if it does not fit in the fixed column width.
   *
   * @type {Boolean}
   * @default true
   * @since 0.11.0
   */
  wordWrap: true,

  /**
   * CSS class name added to cells with cell meta `wordWrap: false`.
   *
   * @type {String}
   * @default 'htNoWrap'
   * @since 0.11.0
   */
  noWordWrapClassName: 'htNoWrap',

  /**
   * @description
   * Defines if the right-click context menu should be enabled. Context menu allows to create new row or
   * column at any place in the grid among [other features](http://docs.handsontable.com/demo-context-menu.html).
   * Possible values:
   * * `true` (to enable default options),
   * * `false` (to disable completely)
   * * an array of [predefined options](https://docs.handsontable.com/demo-context-menu.html#page-specific),
   * * an object [with defined structure](http://docs.handsontable.com/demo-context-menu.html#page-custom)
   *
   * See [the context menu demo](http://docs.handsontable.com/demo-context-menu.html) for examples.
   *
   * @example
   * ```js
   * ...
   * // as a boolean
   * contextMenu: true
   * ...
   * // as an array
   * contextMenu: ['row_above', 'row_below', '--------', 'undo', 'redo']
   * ...
   * ```
   * ...
   * // as an object (`name` attribute is required in the custom keys)
   * contextMenu: {
   *   items: {
   *     "option1": {
   *       name: "option1"
   *     },
   *     "option2": {
   *       name: "option2",
   *       submenu: {
   *         items: [
   *           {
   *             key: "option2:suboption1",
   *             name: "option2:suboption1",
   *             callback: function(key, options) {
   *               ...
   *             }
   *           },
   *           ...
   *         ]
   *       }
   *     }
   *   }
   * }
   * ...
   * ```
   * @type {Boolean|Array|Object}
   * @default undefined
   */
  contextMenu: void 0,

  /**
   * @description
   * Disable or enable the copy/paste functionality.
   *
   * @example
   * ```js
   * ...
   * copyPaste: false,
   * ...
   * ```
   *
   * @type {Boolean}
   * @default true
   */
  copyPaste: true,

  /**
   * If `true`, undo/redo functionality is enabled.
   *
   * @type {Boolean}
   * @default undefined
   */
  undo: void 0,

  /**
   * @description
   * Turns on [Column sorting](http://docs.handsontable.com/demo-sorting-data.html).
   * Can be either a boolean (true/false) or an object with a declared sorting options. See the below example:
   *
   * @example
   * ```js
   * ...
   * // as boolean
   * columnSorting: true
   * ...
   * // as a object with initial order (sort ascending column at index 2)
   * columnSorting: {
   *   column: 2,
   *   sortOrder: true, // true = ascending, false = descending, undefined = original order
   *   sortEmptyCells: true // true = the table sorts empty cells, false = the table moves all empty cells to the end of the table
   * }
   * ...
   * ```
   *
   * @type {Boolean|Object}
   * @default undefined
   */
  columnSorting: void 0,

  /**
   * @description
   * Turns on [Manual column move](http://docs.handsontable.com/demo-moving-rows-and-columns.html), if set to a boolean or define initial
   * column order, if set to an array of column indexes.
   *
   * @example
   * ```js
   * ...
   * // as boolean
   * manualColumnMove: true
   * ...
   * // as a array with initial order (move column index at 0 to 1 and move column index at 1 to 4)
   * manualColumnMove: [1, 4]
   * ...
   * ```
   *
   * @type {Boolean|Array}
   * @default undefined
   */
  manualColumnMove: void 0,

  /**
   * @description
   * Turns on [Manual column resize](http://docs.handsontable.com/demo-resizing.html), if set to a boolean or define initial
   * column resized widths, if set to an array of numbers.
   *
   * @example
   * ```js
   * ...
   * // as boolean
   * manualColumnResize: true
   * ...
   * // as a array with initial widths (column at 0 index has 40px and column at 1 index has 50px)
   * manualColumnResize: [40, 50]
   * ...
   * ```
   *
   * @type {Boolean|Array}
   * @default undefined
   */
  manualColumnResize: void 0,

  /**
   * @description
   * Turns on [Manual row move](http://docs.handsontable.com/demo-moving-rows-and-columns.html), if set to a boolean or define initial
   * row order, if set to an array of row indexes.
   *
   * @example
   * ```js
   * ...
   * // as boolean
   * manualRowMove: true
   * ...
   * // as a array with initial order (move row index at 0 to 1 and move row index at 1 to 4)
   * manualRowMove: [1, 4]
   * ...
   * ```
   *
   * @type {Boolean|Array}
   * @default undefined
   * @since 0.11.0
   */
  manualRowMove: void 0,

  /**
   * @description
   * Turns on [Manual row resize](http://docs.handsontable.com/demo-resizing.html), if set to a boolean or define initial
   * row resized heights, if set to an array of numbers.
   *
   * @example
   * ```js
   * ...
   * // as boolean
   * manualRowResize: true
   * ...
   * // as a array with initial heights (row at 0 index has 40px and row at 1 index has 50px)
   * manualRowResize: [40, 50]
   * ...
   * ```
   *
   * @type {Boolean|Array}
   * @default undefined
   * @since 0.11.0
   */
  manualRowResize: void 0,

  /**
   * @description
   * If set to `true`, it enables a possibility to merge cells. If set to an array of objects, it merges the cells provided in the objects (see the example below).
   * [More information on the demo page.](http://docs.handsontable.com/demo-merge-cells.html)
   *
   * @example
   * ```js
   * // enables the mergeCells plugin:
   * margeCells: true
   * ...
   * // declares a list of merged sections:
   * mergeCells: [
   *   {row: 1, col: 1, rowspan: 3, colspan: 3}, // rowspan and colspan properties declare the width and height of a merged section in cells
   *   {row: 3, col: 4, rowspan: 2, colspan: 2},
   *   {row: 5, col: 6, rowspan: 3, colspan: 3}
   * ]
   * ```
   * @type {Boolean|Array}
   * @default false
   */
  mergeCells: false,

  /**
   * Number of rows to be rendered outside of the visible part of the table.
   * By default, it's set to `'auto'`, which makes Handsontable to attempt to calculate the best offset performance-wise.
   *
   * You may test out different values to find the best one that works for your specific implementation.
   *
   * @type {Number|String}
   * @default 'auto'
   */
  viewportRowRenderingOffset: 'auto',

  /**
   * Number of columns to be rendered outside of the visible part of the table.
   * By default, it's set to `'auto'`, which makes Handsontable try calculating the best offset performance-wise.
   *
   * You may experiment with the value to find the one that works best for your specific implementation.
   *
   * @type {Number|String}
   * @default 'auto'
   */
  viewportColumnRenderingOffset: 'auto',

  /**
   * A function, regular expression or a string, which will be used in the process of cell validation.
   * If a function is used, be sure to execute the callback argument with either `true` (`callback(true)`) if the validation passed
   * or with `false` (`callback(false)`), if the validation failed.
   * Note, that `this` in the function points to the `cellProperties` object.
   *
   * If a string is provided, it may be one of the following predefined values:
   * * `autocomplete`,
   * * `date`,
   * * `numeric`,
   * * `time`.
   *
   * Or you can [register](http://docs.handsontable.com/demo-data-validation.html) the validator function under specified name and use
   * its name as an alias in your configuration.
   *
   * See more [in the demo](http://docs.handsontable.com/demo-data-validation.html).
   *
   * @example
   * ```js
   * // as a function
   * columns: [
   *    {
   *      validator: function(value, callback) { // validation rules }
   *    }
   * ]
   * ...
   * // as a regexp
   * columns: [
   *    {
   *      validator: /^[0-9]$/ // regular expression
   *    }
   * ]
   * // as a string
   * columns: [
   *    {
   *      validator: 'numeric'
   *    }
   * ]
   * ```
   * @type {Function|RegExp|String}
   * @default undefined
   * @since 0.9.5
   */
  validator: void 0,

  /**
   * @description
   * Disable visual cells selection.
   *
   * Possible values:
   *  * `true` - Disables any type of visual selection (current and area selection),
   *  * `false` - Enables any type of visual selection. This is default value.
   *  * `current` - Disables the selection of a currently selected cell, the area selection is still present.
   *  * `area` - Disables the area selection, the currently selected cell selection is still present.
   *
   * @type {Boolean|String|Array}
   * @default false
   * @since 0.13.2
   * @example
   * ```js
   * ...
   * // as boolean
   * disableVisualSelection: true,
   * ...
   *
   * ...
   * // as string ('current' or 'area')
   * disableVisualSelection: 'current',
   * ...
   *
   * ...
   * // as array
   * disableVisualSelection: ['current', 'area'],
   * ...
   * ```
   */
  disableVisualSelection: false,

  /**
   * @description
   * Set whether to display the current sorting order indicator (a triangle icon in the column header, specifying the sorting order).
   *
   * @type {Boolean}
   * @default false
   * @since 0.15.0-beta3
   */
  sortIndicator: void 0,

  /**
   * Disable or enable ManualColumnFreeze plugin.
   *
   * @type {Boolean}
   * @default false
   */
  manualColumnFreeze: void 0,

  /**
   * @description
   * Defines whether Handsontable should trim the whitespace at the beginning and the end of the cell contents.
   *
   * @type {Boolean}
   * @default true
   */
  trimWhitespace: true,

  settings: void 0,

  /**
   * @description
   * Defines data source for Autocomplete or Dropdown cell types.
   *
   * @example
   * ```js
   * ...
   * // source as a array
   * columns: [{
   *   type: 'autocomplete',
   *   source: ['A', 'B', 'C', 'D']
   * }]
   * ...
   * // source as a function
   * columns: [{
   *   type: 'autocomplete',
   *   source: function(query, callback) {
   *     fetch('http://example.com/query?q=' + query, function(response) {
   *       callback(response.items);
   *     })
   *   }
   * }]
   * ...
   * ```
   *
   * @type {Array|Function}
   * @default undefined
   */
  source: void 0,

  /**
   * @description
   * Defines the column header name.
   *
   * @example
   * ```js
   * ...
   * columns: [{
   *     title: 'First name',
   *     type: 'text',
   *   },
   *   {
   *     title: 'Last name',
   *     type: 'text',
   *   }]
   * ...
   * ```
   *
   * @type {String}
   * @default undefined
   */
  title: void 0,

  /**
   * Data template for `'checkbox'` type when checkbox is checked.
   *
   * @example
   * ```js
   * checkedTemplate: 'good'
   *
   * // if a checkbox-typed cell is checked, then getDataAtCell(x,y), where x and y are the coordinates of the cell
   * // will return 'good'.
   * ```
   * @type {Boolean|String}
   * @default true
   */
  checkedTemplate: void 0,

  /**
   * Data template for `'checkbox'` type when checkbox is unchecked.
   *
   * @example
   * ```js
   * uncheckedTemplate: 'bad'
   *
   * // if a checkbox-typed cell is not checked, then getDataAtCell(x,y), where x and y are the coordinates of the cell
   * // will return 'bad'.
   * ```
   * @type {Boolean|String}
   * @default false
   */
  uncheckedTemplate: void 0,

  /**
   * @description
   * Object which describes if renderer should create checkbox element with label element as a parent. Option desired for
   * [checkbox](http://docs.handsontable.com/demo-checkbox.html)-typed cells.
   *
   * By default the [checkbox](http://docs.handsontable.com/demo-checkbox.html) renderer renders the checkbox without a label.
   *
   * Possible object properties:
   *  * `property` - Defines the property name of the data object, which will to be used as a label.
   *  (eg. `label: {property: 'name.last'}`). This option works only if data was passed as an array of objects.
   *  * `position` - String which describes where to place the label text (before or after checkbox element).
   * Valid values are `'before'` and '`after`' (defaults to `'after'`).
   *  * `value` - String or a Function which will be used as label text.
   *
   * @example
   * ```js
   * ...
   * columns: [{
   *   type: 'checkbox',
   *   label: {position: 'after', value: 'My label: '}
   * }]
   * ...
   * ```
   *
   * @since 0.19.0
   * @type {Object}
   * @default undefined
   */
  label: void 0,

  /**
   * Display format. See [numbrojs](http://numbrojs.com). This option is desired for
   * [numeric](http://docs.handsontable.com/demo-numeric.html)-typed cells.
   *
   * Since 0.26.0 Handsontable uses [numbro](http://numbrojs.com/) as a main library for numbers formatting.
   *
   * @example
   * ```js
   * ...
   * columns: [{
   *   type: 'numeric',
   *   format: '0,00'
   * }]
   * ...
   * ```
   *
   * @type {String}
   * @default '0'
   */
  format: void 0,

  /**
   * Language display format. See [numbrojs](http://numbrojs.com/languages.html#supported-languages). This option is desired for
   * [numeric](http://docs.handsontable.com/demo-numeric.html)-typed cells.
   *
   * Since 0.26.0 Handsontable uses [numbro](http://numbrojs.com/) as a main library for numbers formatting.
   *
   * @example
   * ```js
   * ...
   * columns: [{
   *   type: 'numeric',
   *   language: 'en-US'
   * }]
   * ...
   * ```
   *
   * @type {String}
   * @default 'en-US'
   */
  language: void 0,

  /**
   * @description
   * Data source for [select](http://docs.handsontable.com/demo-select.html)-typed cells.
   *
   * @example
   * ```js
   * ...
   * columns: [{
   *   editor: 'select',
   *   selectOptions: ['A', 'B', 'C'],
   * }]
   * ...
   * ```
   *
   * @type {Array}
   */
  selectOptions: void 0,

  /**
   * Enables or disables the autoColumnSize plugin. Default value is `undefined`, which has the same effect as `true`.
   * Disabling this plugin can increase performance, as no size-related calculations would be done.
   *
   * Column width calculations are divided into sync and async part. Each of this parts has their own advantages and
   * disadvantages. Synchronous calculations are faster but they block the browser UI, while the slower asynchronous operations don't
   * block the browser UI.
   *
   * To configure the sync/async distribution, you can pass an absolute value (number of columns) or a percentage value.
   * `syncLimit` option is available since 0.16.0.
   *
   * You can also use the `useHeaders` option to take the column headers with into calculation.
   *
   * @example
   * ```js
   * ...
   * // as a number (300 columns in sync, rest async)
   * autoColumnSize: {syncLimit: 300},
   * ...
   *
   * ...
   * // as a string (percent)
   * autoColumnSize: {syncLimit: '40%'},
   * ...
   *
   * ...
   * // use headers width while calculation the column width
   * autoColumnSize: {useHeaders: true},
   * ...
   *
   * ```
   *
   * @type {Object|Boolean}
   * @default {syncLimit: 50}
   */
  autoColumnSize: void 0,

  /**
   * Enables or disables autoRowSize plugin. Default value is `undefined`, which has the same effect as `false` (disabled).
   * Enabling this plugin can decrease performance, as size-related calculations would be performed.
   *
   * Row height calculations are divided into sync and async stages. Each of these stages has their own advantages and
   * disadvantages. Synchronous calculations are faster but they block the browser UI, while the slower asynchronous operations don't
   * block the browser UI.
   *
   * To configure the sync/async distribution, you can pass an absolute value (number of columns) or a percentage value.
   * `syncLimit` options is available since 0.16.0.
   *
   * @example
   * ```js
   * ...
   * // as number (300 columns in sync, rest async)
   * autoRowSize: {syncLimit: 300},
   * ...
   *
   * ...
   * // as string (percent)
   * autoRowSize: {syncLimit: '40%'},
   * ...
   * ```
   * @type {Object|Boolean}
   * @default {syncLimit: 1000}
   */
  autoRowSize: void 0,

  /**
   * Date validation format.
   *
   * Option desired for `'date'` - typed cells.
   *
   * @example
   * ```js
   * ...
   * columns: [{
   *   type: 'date',
   *   dateFormat: 'MM/DD/YYYY'
   * }]
   * ...
   * ```
   *
   * @type {String}
   * @default 'DD/MM/YYYY'
   */
  dateFormat: void 0,

  /**
   * If `true` then dates will be automatically formatted to match the desired format.
   *
   * Option desired for `'date'`-typed typed cells.
   *
   * @example
   * ```js
   * ...
   * columns: [{
   *   type: 'date',
   *   dateFormat: 'YYYY-MM-DD',
   *   correctFormat: true
   * }]
   * ...
   * ```
   *
   * @type {Boolean}
   * @default false
   */
  correctFormat: false,

  /**
   * Definition of default value which will fill the empty cells.
   *
   * Option desired for `'date'`-typed cells.
   *
   * @example
   * ```js
   * ...
   * columns: [{
   *   type: 'date',
   *   defaultData: '2015-02-02'
   * }]
   * ...
   * ```
   *
   * @type {String}
   */
  defaultDate: void 0,

  /**
   * If set to `true`, the value entered into the cell must match (case-sensitive) the autocomplete source. Otherwise, cell won't pass the validation.
   * When filtering the autocomplete source list, the editor will be working in case-insensitive mode.
   *
   * Option desired for `autocomplete`-typed cells.
   *
   * @example
   * ```js
   * ...
   * columns: [{
   *   type: 'autocomplete',
   *   source: ['A', 'B', 'C'],
   *   strict: true
   * }]
   * ...
   * ```
   *
   * @type {Boolean}
   */
  strict: void 0,

  /**
   * @description
   * If typed `true`, data defined in `source` of the autocomplete or dropdown cell will be treated as HTML.
   *
   * __Warning:__ Enabling this option can cause serious XSS vulnerabilities.
   *
   * Option desired for `'autocomplete'`-typed cells.
   * @example
   * ```js
   * ...
   * columns: [{
   *   type: 'autocomplete',
   *   allowHtml: true,
   *   source: ['<b>foo</b>', '<b>bar</b>']
   * }]
   * ...
   * ```
   * @type {Boolean}
   * @default false
   */
  allowHtml: false,

  /**
   * If typed `true` then virtual rendering mechanism for handsontable will be disabled.
   *
   * @type {Boolean}
   */
  renderAllRows: void 0,

  /**
   * Prevents table to overlap outside the parent element. If `'horizontal'` option is chosen then table will appear horizontal
   * scrollbar in case where parent's width is narrower then table's width.
   *
   * Possible values:
   *  * `false` - Disables functionality (Default option).
   *  * `horizontal` - Prevents horizontal overflow table.
   *  * `vertical` - Prevents vertical overflow table (Not implemented yet).
   *
   * @since 0.20.3
   * @example
   * ```js
   * ...
   * preventOverflow: 'horizontal'
   * ...
   * ```
   *
   * @type {String|Boolean}
   */
  preventOverflow: false,

  /**
   * @description
   * Plugin allowing binding the table rows with their headers.
   * If the plugin is enabled, the table row headers will "stick" to the rows, when they are hidden/moved. Basically, if at the initialization
   * row 0 has a header titled "A", it will have it no matter what you do with the table.
   *
   * @pro
   * @since 1.0.0-beta1
   * @type {Boolean|String}
   * @example
   *
   * ```js
   * ...
   * var hot = new Handsontable(document.getElementById('example'), {
   *   date: getData(),
   *   bindRowsWithHeaders: true
   * });
   * ...
   * ```
   *
   */
  bindRowsWithHeaders: void 0,

  /**
   * @description
   * The CollapsibleColumns plugin allows collapsing of columns, covered by a header with the `colspan` property defined.
   *
   * Clicking the "collapse/expand" button collapses (or expands) all "child" headers except the first one.
   *
   * Setting the `collapsibleColumns` property to `true` will display a "collapse/expand" button in every header with a defined
   * `colspan` property.
   *
   * To limit this functionality to a smaller group of headers, define the `collapsibleColumns` property as an array of objects, as in
   * the example below.
   *
   * @pro
   * @since 1.0.0-beta1
   * @type {Boolean|Array}
   * @example
   * ```js
   * ...
   *  collapsibleColumns: [
   *    {row: -4, col: 1, collapsible: true},
   *    {row: -3, col: 5, collapsible: true}
   *  ]
   * ...
   * // or
   * ...
   *  collapsibleColumns: true
   * ...
   * ```
   */
  collapsibleColumns: void 0,

  /**
   * @description
   * Allows making pre-defined calculations on the cell values and display the results within Handsontable.
   * See the demo for more information.
   *
   * @pro
   * @since 1.0.0-beta1
   * @type {Object}
   */
  columnSummary: void 0,

  /**
   * This plugin allows adding a configurable dropdown menu to the table's column headers.
   * The dropdown menu acts like the Context Menu, but is triggered by clicking the button in the header.
   *
   * @pro
   * @since 1.0.0-beta1
   * @type {Boolean|Object|Array}
   */
  dropdownMenu: void 0,

  /**
   * The filters plugin.
   * It allows filtering the table data either by the built-in component or with the API.
   *
   * @pro
   * @since 1.0.0-beta1
   * @type {Boolean}
   */
  filters: void 0,

  /**
   * It allows Handsontable to process formula expressions defined in the provided data.
   *
   * @pro
   * @since 1.7.0
   * @type {Boolean}
   */
  formulas: void 0,

  /**
   * @description
   * GanttChart plugin enables a possibility to create a Gantt chart using a Handsontable instance.
   * In this case, the whole table becomes read-only.
   *
   * @pro
   * @since 1.0.0-beta1
   * @type {Object}
   */
  ganttChart: void 0,

  /**
   * @description
   * Allows adding a tooltip to the table headers.
   *
   * Available options:
   * * the `rows` property defines if tooltips should be added to row headers,
   * * the `columns` property defines if tooltips should be added to column headers,
   * * the `onlyTrimmed` property defines if tooltips should be added only to headers, which content is trimmed by the header itself (the content being wider then the header).
   *
   * @pro
   * @since 1.0.0-beta1
   * @type {Boolean|Object}
   */
  headerTooltips: void 0,

  /**
   * Plugin allowing hiding of certain columns.
   *
   * @pro
   * @since 1.0.0-beta1
   * @type {Boolean|Object}
   */
  hiddenColumns: void 0,

  /**
   * @description
   * Plugin allowing hiding of certain rows.
   *
   * @pro
   * @since 1.0.0-beta1
   * @type {Boolean|Object}
   */
  hiddenRows: void 0,

  /**
   * @description
   * Allows creating a nested header structure, using the HTML's colspan attribute.
   *
   * @pro
   * @since 1.0.0-beta1
   * @type {Array}
   */
  nestedHeaders: void 0,

  /**
   * @description
   * Plugin allowing hiding of certain rows.
   *
   * @pro
   * @since 1.0.0-beta1
   * @type {Boolean|Array}
   */
  trimRows: void 0,

  /**
   * @description
   * Allows setting a custom width of the row headers. You can provide a number or an array of widths, if many row header levels are defined.
   *
   * @since 0.22.0
   * @type {Number|Array}
   */
  rowHeaderWidth: void 0,

  /**
   * @description
   * Allows setting a custom height of the column headers. You can provide a number or an array of heights, if many column header levels are defined.
   *
   * @since 0.22.0
   * @type {Number|Array}
   */
  columnHeaderHeight: void 0,

  /**
   * @description
   * Enabling this plugin switches table into one-way data binding where changes are applied into data source (from outside table)
   * will be automatically reflected in the table.
   *
   * For every data change [afterChangesObserved](Hooks.html#event:afterChangesObserved) hook will be fired.
   *
   * @type {Boolean}
   * @default false
   */
  observeChanges: void 0,

  /**
   * @description
   * When passed to the `column` property, allows specifying a custom sorting function for the desired column.
   *
   * @since 0.24.0
   * @type {Function}
   * @example
   * ```js
   * columns: [
   *   {
   *     sortFunction: function(sortOrder) {
   *        return function(a, b) {
   *          // sorting function body.
   *          //
   *          // Function parameters:
   *          // sortOrder: If true, the order is ascending, if false - descending. undefined = original order
   *          // a, b: Two compared elements. These are 2-element arrays, with the first element being the row index, the second - cell value.
   *        }
   *     }
   *   }
   * ]
   * ```
   */
  sortFunction: void 0,

  /**
   * If defined as 'true', the Autocomplete's suggestion list would be sorted by relevance (the closer to the left the match is, the higher the suggestion).
   *
   * Option desired for cells of the `'autocomplete'` type.
   *
   * @type {Boolean}
   * @default true
   */
  sortByRelevance: true,

  /**
   * If defined as 'true', when the user types into the input area the Autocomplete's suggestion list is updated to only
   * include those choices starting with what has been typed; if defined as 'false' all suggestions remain shown, with
   * those matching what has been typed marked in bold.
   *
   * @type {Boolean}
   * @default true
   */
  filter: true,

  /**
   * If defined as 'true', filtering in the Autocomplete Editor will be case-sensitive.
   *
   * @type {Boolean}
   * @default: false
   */
  filteringCaseSensitive: false
};

exports.default = DefaultSettings;

/***/ }),
/* 89 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


exports.__esModule = true;
exports.getNormalizedDate = getNormalizedDate;
/* eslint-disable import/prefer-default-export */

/**
 * Get normalized Date object for the ISO formatted date strings.
 * Natively, the date object parsed from a ISO 8601 string will be offsetted by the timezone difference, which may result in returning a wrong date.
 * See: Github issue #3338.
 *
 * @param {String} dateString String representing the date.
 * @returns {Date} The proper Date object.
 */
function getNormalizedDate(dateString) {
  var nativeDate = new Date(dateString);

  // NaN if dateString is not in ISO format
  if (!isNaN(new Date(dateString + "T00:00").getDate())) {

    // Compensate timezone offset
    return new Date(nativeDate.getTime() + nativeDate.getTimezoneOffset() * 60000);
  }

  return nativeDate;
}

/***/ }),
/* 90 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


exports.__esModule = true;
exports.registerAsRootInstance = registerAsRootInstance;
exports.hasValidParameter = hasValidParameter;
exports.isRootInstance = isRootInstance;
var holder = exports.holder = new WeakMap();

var rootInstanceSymbol = exports.rootInstanceSymbol = Symbol('rootInstance');

/**
 * Register an object as a root instance.
 *
 * @param  {Object} object An object to associate with root instance flag.
 */
function registerAsRootInstance(object) {
  holder.set(object, true);
}

/**
 * Check if the source of the root indication call is valid.
 *
 * @param  {Symbol} rootSymbol A symbol as a source of truth.
 * @return {Boolean}
 */
function hasValidParameter(rootSymbol) {
  return rootSymbol === rootInstanceSymbol;
}

/**
 * Check if passed an object was flagged as a root instance.
 *
 * @param  {Object} object An object to check.
 * @return {Boolean}
 */
function isRootInstance(object) {
  return holder.has(object);
}

/***/ }),
/* 91 */
/***/ (function(module, exports, __webpack_require__) {

// 22.1.3.3 Array.prototype.copyWithin(target, start, end = this.length)
var $export = __webpack_require__(1);

$export($export.P, 'Array', { copyWithin: __webpack_require__(389) });

__webpack_require__(37)('copyWithin');


/***/ }),
/* 92 */
/***/ (function(module, exports, __webpack_require__) {

// 22.1.3.6 Array.prototype.fill(value, start = 0, end = this.length)
var $export = __webpack_require__(1);

$export($export.P, 'Array', { fill: __webpack_require__(390) });

__webpack_require__(37)('fill');


/***/ }),
/* 93 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";

// 22.1.3.9 Array.prototype.findIndex(predicate, thisArg = undefined)
var $export = __webpack_require__(1);
var $find = __webpack_require__(56)(6);
var KEY = 'findIndex';
var forced = true;
// Shouldn't skip holes
if (KEY in []) Array(1)[KEY](function () { forced = false; });
$export($export.P + $export.F * forced, 'Array', {
  findIndex: function findIndex(callbackfn /* , that = undefined */) {
    return $find(this, callbackfn, arguments.length > 1 ? arguments[1] : undefined);
  }
});
__webpack_require__(37)(KEY);


/***/ }),
/* 94 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";

// 22.1.3.8 Array.prototype.find(predicate, thisArg = undefined)
var $export = __webpack_require__(1);
var $find = __webpack_require__(56)(5);
var KEY = 'find';
var forced = true;
// Shouldn't skip holes
if (KEY in []) Array(1)[KEY](function () { forced = false; });
$export($export.P + $export.F * forced, 'Array', {
  find: function find(callbackfn /* , that = undefined */) {
    return $find(this, callbackfn, arguments.length > 1 ? arguments[1] : undefined);
  }
});
__webpack_require__(37)(KEY);


/***/ }),
/* 95 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";

var ctx = __webpack_require__(30);
var $export = __webpack_require__(1);
var toObject = __webpack_require__(40);
var call = __webpack_require__(280);
var isArrayIter = __webpack_require__(276);
var toLength = __webpack_require__(21);
var createProperty = __webpack_require__(74);
var getIterFn = __webpack_require__(292);

$export($export.S + $export.F * !__webpack_require__(79)(function (iter) { Array.from(iter); }), 'Array', {
  // 22.1.2.1 Array.from(arrayLike, mapfn = undefined, thisArg = undefined)
  from: function from(arrayLike /* , mapfn = undefined, thisArg = undefined */) {
    var O = toObject(arrayLike);
    var C = typeof this == 'function' ? this : Array;
    var aLen = arguments.length;
    var mapfn = aLen > 1 ? arguments[1] : undefined;
    var mapping = mapfn !== undefined;
    var index = 0;
    var iterFn = getIterFn(O);
    var length, result, step, iterator;
    if (mapping) mapfn = ctx(mapfn, aLen > 2 ? arguments[2] : undefined, 2);
    // if object isn't iterable or it's array with default iterator - use simple case
    if (iterFn != undefined && !(C == Array && isArrayIter(iterFn))) {
      for (iterator = iterFn.call(O), result = new C(); !(step = iterator.next()).done; index++) {
        createProperty(result, index, mapping ? call(iterator, mapfn, [step.value, index], true) : step.value);
      }
    } else {
      length = toLength(O.length);
      for (result = new C(length); length > index; index++) {
        createProperty(result, index, mapping ? mapfn(O[index], index) : O[index]);
      }
    }
    result.length = index;
    return result;
  }
});


/***/ }),
/* 96 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";

var $export = __webpack_require__(1);
var createProperty = __webpack_require__(74);

// WebKit Array.of isn't generic
$export($export.S + $export.F * __webpack_require__(25)(function () {
  function F() { /* empty */ }
  return !(Array.of.call(F) instanceof F);
}), 'Array', {
  // 22.1.2.3 Array.of( ...items)
  of: function of(/* ...args */) {
    var index = 0;
    var aLen = arguments.length;
    var result = new (typeof this == 'function' ? this : Array)(aLen);
    while (aLen > index) createProperty(result, index, arguments[index++]);
    result.length = aLen;
    return result;
  }
});


/***/ }),
/* 97 */
/***/ (function(module, exports, __webpack_require__) {

var dP = __webpack_require__(18).f;
var FProto = Function.prototype;
var nameRE = /^\s*function ([^ (]*)/;
var NAME = 'name';

// 19.2.4.2 name
NAME in FProto || __webpack_require__(20) && dP(FProto, NAME, {
  configurable: true,
  get: function () {
    try {
      return ('' + this).match(nameRE)[1];
    } catch (e) {
      return '';
    }
  }
});


/***/ }),
/* 98 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";

var strong = __webpack_require__(272);
var validate = __webpack_require__(41);
var MAP = 'Map';

// 23.1 Map Objects
module.exports = __webpack_require__(57)(MAP, function (get) {
  return function Map() { return get(this, arguments.length > 0 ? arguments[0] : undefined); };
}, {
  // 23.1.3.6 Map.prototype.get(key)
  get: function get(key) {
    var entry = strong.getEntry(validate(this, MAP), key);
    return entry && entry.v;
  },
  // 23.1.3.9 Map.prototype.set(key, value)
  set: function set(key, value) {
    return strong.def(validate(this, MAP), key === 0 ? 0 : key, value);
  }
}, strong, true);


/***/ }),
/* 99 */
/***/ (function(module, exports, __webpack_require__) {

// 20.1.2.1 Number.EPSILON
var $export = __webpack_require__(1);

$export($export.S, 'Number', { EPSILON: Math.pow(2, -52) });


/***/ }),
/* 100 */
/***/ (function(module, exports, __webpack_require__) {

// 20.1.2.2 Number.isFinite(number)
var $export = __webpack_require__(1);
var _isFinite = __webpack_require__(10).isFinite;

$export($export.S, 'Number', {
  isFinite: function isFinite(it) {
    return typeof it == 'number' && _isFinite(it);
  }
});


/***/ }),
/* 101 */
/***/ (function(module, exports, __webpack_require__) {

// 20.1.2.3 Number.isInteger(number)
var $export = __webpack_require__(1);

$export($export.S, 'Number', { isInteger: __webpack_require__(278) });


/***/ }),
/* 102 */
/***/ (function(module, exports, __webpack_require__) {

// 20.1.2.4 Number.isNaN(number)
var $export = __webpack_require__(1);

$export($export.S, 'Number', {
  isNaN: function isNaN(number) {
    // eslint-disable-next-line no-self-compare
    return number != number;
  }
});


/***/ }),
/* 103 */
/***/ (function(module, exports, __webpack_require__) {

// 20.1.2.5 Number.isSafeInteger(number)
var $export = __webpack_require__(1);
var isInteger = __webpack_require__(278);
var abs = Math.abs;

$export($export.S, 'Number', {
  isSafeInteger: function isSafeInteger(number) {
    return isInteger(number) && abs(number) <= 0x1fffffffffffff;
  }
});


/***/ }),
/* 104 */
/***/ (function(module, exports, __webpack_require__) {

// 20.1.2.6 Number.MAX_SAFE_INTEGER
var $export = __webpack_require__(1);

$export($export.S, 'Number', { MAX_SAFE_INTEGER: 0x1fffffffffffff });


/***/ }),
/* 105 */
/***/ (function(module, exports, __webpack_require__) {

// 20.1.2.10 Number.MIN_SAFE_INTEGER
var $export = __webpack_require__(1);

$export($export.S, 'Number', { MIN_SAFE_INTEGER: -0x1fffffffffffff });


/***/ }),
/* 106 */
/***/ (function(module, exports, __webpack_require__) {

// 19.1.3.1 Object.assign(target, source)
var $export = __webpack_require__(1);

$export($export.S + $export.F, 'Object', { assign: __webpack_require__(284) });


/***/ }),
/* 107 */
/***/ (function(module, exports, __webpack_require__) {

// 19.1.3.10 Object.is(value1, value2)
var $export = __webpack_require__(1);
$export($export.S, 'Object', { is: __webpack_require__(405) });


/***/ }),
/* 108 */
/***/ (function(module, exports, __webpack_require__) {

// 19.1.3.19 Object.setPrototypeOf(O, proto)
var $export = __webpack_require__(1);
$export($export.S, 'Object', { setPrototypeOf: __webpack_require__(287).set });


/***/ }),
/* 109 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";

var LIBRARY = __webpack_require__(60);
var global = __webpack_require__(10);
var ctx = __webpack_require__(30);
var classof = __webpack_require__(271);
var $export = __webpack_require__(1);
var isObject = __webpack_require__(12);
var aFunction = __webpack_require__(54);
var anInstance = __webpack_require__(55);
var forOf = __webpack_require__(59);
var speciesConstructor = __webpack_require__(406);
var task = __webpack_require__(86).set;
var microtask = __webpack_require__(398)();
var newPromiseCapabilityModule = __webpack_require__(283);
var perform = __webpack_require__(403);
var promiseResolve = __webpack_require__(404);
var PROMISE = 'Promise';
var TypeError = global.TypeError;
var process = global.process;
var $Promise = global[PROMISE];
var isNode = classof(process) == 'process';
var empty = function () { /* empty */ };
var Internal, newGenericPromiseCapability, OwnPromiseCapability, Wrapper;
var newPromiseCapability = newGenericPromiseCapability = newPromiseCapabilityModule.f;

var USE_NATIVE = !!function () {
  try {
    // correct subclassing with @@species support
    var promise = $Promise.resolve(1);
    var FakePromise = (promise.constructor = {})[__webpack_require__(8)('species')] = function (exec) {
      exec(empty, empty);
    };
    // unhandled rejections tracking support, NodeJS Promise without it fails @@species test
    return (isNode || typeof PromiseRejectionEvent == 'function') && promise.then(empty) instanceof FakePromise;
  } catch (e) { /* empty */ }
}();

// helpers
var isThenable = function (it) {
  var then;
  return isObject(it) && typeof (then = it.then) == 'function' ? then : false;
};
var notify = function (promise, isReject) {
  if (promise._n) return;
  promise._n = true;
  var chain = promise._c;
  microtask(function () {
    var value = promise._v;
    var ok = promise._s == 1;
    var i = 0;
    var run = function (reaction) {
      var handler = ok ? reaction.ok : reaction.fail;
      var resolve = reaction.resolve;
      var reject = reaction.reject;
      var domain = reaction.domain;
      var result, then;
      try {
        if (handler) {
          if (!ok) {
            if (promise._h == 2) onHandleUnhandled(promise);
            promise._h = 1;
          }
          if (handler === true) result = value;
          else {
            if (domain) domain.enter();
            result = handler(value);
            if (domain) domain.exit();
          }
          if (result === reaction.promise) {
            reject(TypeError('Promise-chain cycle'));
          } else if (then = isThenable(result)) {
            then.call(result, resolve, reject);
          } else resolve(result);
        } else reject(value);
      } catch (e) {
        reject(e);
      }
    };
    while (chain.length > i) run(chain[i++]); // variable length - can't use forEach
    promise._c = [];
    promise._n = false;
    if (isReject && !promise._h) onUnhandled(promise);
  });
};
var onUnhandled = function (promise) {
  task.call(global, function () {
    var value = promise._v;
    var unhandled = isUnhandled(promise);
    var result, handler, console;
    if (unhandled) {
      result = perform(function () {
        if (isNode) {
          process.emit('unhandledRejection', value, promise);
        } else if (handler = global.onunhandledrejection) {
          handler({ promise: promise, reason: value });
        } else if ((console = global.console) && console.error) {
          console.error('Unhandled promise rejection', value);
        }
      });
      // Browsers should not trigger `rejectionHandled` event if it was handled here, NodeJS - should
      promise._h = isNode || isUnhandled(promise) ? 2 : 1;
    } promise._a = undefined;
    if (unhandled && result.e) throw result.v;
  });
};
var isUnhandled = function (promise) {
  if (promise._h == 1) return false;
  var chain = promise._a || promise._c;
  var i = 0;
  var reaction;
  while (chain.length > i) {
    reaction = chain[i++];
    if (reaction.fail || !isUnhandled(reaction.promise)) return false;
  } return true;
};
var onHandleUnhandled = function (promise) {
  task.call(global, function () {
    var handler;
    if (isNode) {
      process.emit('rejectionHandled', promise);
    } else if (handler = global.onrejectionhandled) {
      handler({ promise: promise, reason: promise._v });
    }
  });
};
var $reject = function (value) {
  var promise = this;
  if (promise._d) return;
  promise._d = true;
  promise = promise._w || promise; // unwrap
  promise._v = value;
  promise._s = 2;
  if (!promise._a) promise._a = promise._c.slice();
  notify(promise, true);
};
var $resolve = function (value) {
  var promise = this;
  var then;
  if (promise._d) return;
  promise._d = true;
  promise = promise._w || promise; // unwrap
  try {
    if (promise === value) throw TypeError("Promise can't be resolved itself");
    if (then = isThenable(value)) {
      microtask(function () {
        var wrapper = { _w: promise, _d: false }; // wrap
        try {
          then.call(value, ctx($resolve, wrapper, 1), ctx($reject, wrapper, 1));
        } catch (e) {
          $reject.call(wrapper, e);
        }
      });
    } else {
      promise._v = value;
      promise._s = 1;
      notify(promise, false);
    }
  } catch (e) {
    $reject.call({ _w: promise, _d: false }, e); // wrap
  }
};

// constructor polyfill
if (!USE_NATIVE) {
  // 25.4.3.1 Promise(executor)
  $Promise = function Promise(executor) {
    anInstance(this, $Promise, PROMISE, '_h');
    aFunction(executor);
    Internal.call(this);
    try {
      executor(ctx($resolve, this, 1), ctx($reject, this, 1));
    } catch (err) {
      $reject.call(this, err);
    }
  };
  // eslint-disable-next-line no-unused-vars
  Internal = function Promise(executor) {
    this._c = [];             // <- awaiting reactions
    this._a = undefined;      // <- checked in isUnhandled reactions
    this._s = 0;              // <- state
    this._d = false;          // <- done
    this._v = undefined;      // <- value
    this._h = 0;              // <- rejection state, 0 - default, 1 - handled, 2 - unhandled
    this._n = false;          // <- notify
  };
  Internal.prototype = __webpack_require__(62)($Promise.prototype, {
    // 25.4.5.3 Promise.prototype.then(onFulfilled, onRejected)
    then: function then(onFulfilled, onRejected) {
      var reaction = newPromiseCapability(speciesConstructor(this, $Promise));
      reaction.ok = typeof onFulfilled == 'function' ? onFulfilled : true;
      reaction.fail = typeof onRejected == 'function' && onRejected;
      reaction.domain = isNode ? process.domain : undefined;
      this._c.push(reaction);
      if (this._a) this._a.push(reaction);
      if (this._s) notify(this, false);
      return reaction.promise;
    },
    // 25.4.5.1 Promise.prototype.catch(onRejected)
    'catch': function (onRejected) {
      return this.then(undefined, onRejected);
    }
  });
  OwnPromiseCapability = function () {
    var promise = new Internal();
    this.promise = promise;
    this.resolve = ctx($resolve, promise, 1);
    this.reject = ctx($reject, promise, 1);
  };
  newPromiseCapabilityModule.f = newPromiseCapability = function (C) {
    return C === $Promise || C === Wrapper
      ? new OwnPromiseCapability(C)
      : newGenericPromiseCapability(C);
  };
}

$export($export.G + $export.W + $export.F * !USE_NATIVE, { Promise: $Promise });
__webpack_require__(50)($Promise, PROMISE);
__webpack_require__(288)(PROMISE);
Wrapper = __webpack_require__(45)[PROMISE];

// statics
$export($export.S + $export.F * !USE_NATIVE, PROMISE, {
  // 25.4.4.5 Promise.reject(r)
  reject: function reject(r) {
    var capability = newPromiseCapability(this);
    var $$reject = capability.reject;
    $$reject(r);
    return capability.promise;
  }
});
$export($export.S + $export.F * (LIBRARY || !USE_NATIVE), PROMISE, {
  // 25.4.4.6 Promise.resolve(x)
  resolve: function resolve(x) {
    return promiseResolve(LIBRARY && this === Wrapper ? $Promise : this, x);
  }
});
$export($export.S + $export.F * !(USE_NATIVE && __webpack_require__(79)(function (iter) {
  $Promise.all(iter)['catch'](empty);
})), PROMISE, {
  // 25.4.4.1 Promise.all(iterable)
  all: function all(iterable) {
    var C = this;
    var capability = newPromiseCapability(C);
    var resolve = capability.resolve;
    var reject = capability.reject;
    var result = perform(function () {
      var values = [];
      var index = 0;
      var remaining = 1;
      forOf(iterable, false, function (promise) {
        var $index = index++;
        var alreadyCalled = false;
        values.push(undefined);
        remaining++;
        C.resolve(promise).then(function (value) {
          if (alreadyCalled) return;
          alreadyCalled = true;
          values[$index] = value;
          --remaining || resolve(values);
        }, reject);
      });
      --remaining || resolve(values);
    });
    if (result.e) reject(result.v);
    return capability.promise;
  },
  // 25.4.4.4 Promise.race(iterable)
  race: function race(iterable) {
    var C = this;
    var capability = newPromiseCapability(C);
    var reject = capability.reject;
    var result = perform(function () {
      forOf(iterable, false, function (promise) {
        C.resolve(promise).then(capability.resolve, reject);
      });
    });
    if (result.e) reject(result.v);
    return capability.promise;
  }
});


/***/ }),
/* 110 */
/***/ (function(module, exports, __webpack_require__) {

// 21.2.5.3 get RegExp.prototype.flags()
if (__webpack_require__(20) && /./g.flags != 'g') __webpack_require__(18).f(RegExp.prototype, 'flags', {
  configurable: true,
  get: __webpack_require__(394)
});


/***/ }),
/* 111 */
/***/ (function(module, exports, __webpack_require__) {

// @@match logic
__webpack_require__(58)('match', 1, function (defined, MATCH, $match) {
  // 21.1.3.11 String.prototype.match(regexp)
  return [function match(regexp) {
    'use strict';
    var O = defined(this);
    var fn = regexp == undefined ? undefined : regexp[MATCH];
    return fn !== undefined ? fn.call(regexp, O) : new RegExp(regexp)[MATCH](String(O));
  }, $match];
});


/***/ }),
/* 112 */
/***/ (function(module, exports, __webpack_require__) {

// @@replace logic
__webpack_require__(58)('replace', 2, function (defined, REPLACE, $replace) {
  // 21.1.3.14 String.prototype.replace(searchValue, replaceValue)
  return [function replace(searchValue, replaceValue) {
    'use strict';
    var O = defined(this);
    var fn = searchValue == undefined ? undefined : searchValue[REPLACE];
    return fn !== undefined
      ? fn.call(searchValue, O, replaceValue)
      : $replace.call(String(O), searchValue, replaceValue);
  }, $replace];
});


/***/ }),
/* 113 */
/***/ (function(module, exports, __webpack_require__) {

// @@search logic
__webpack_require__(58)('search', 1, function (defined, SEARCH, $search) {
  // 21.1.3.15 String.prototype.search(regexp)
  return [function search(regexp) {
    'use strict';
    var O = defined(this);
    var fn = regexp == undefined ? undefined : regexp[SEARCH];
    return fn !== undefined ? fn.call(regexp, O) : new RegExp(regexp)[SEARCH](String(O));
  }, $search];
});


/***/ }),
/* 114 */
/***/ (function(module, exports, __webpack_require__) {

// @@split logic
__webpack_require__(58)('split', 2, function (defined, SPLIT, $split) {
  'use strict';
  var isRegExp = __webpack_require__(279);
  var _split = $split;
  var $push = [].push;
  var $SPLIT = 'split';
  var LENGTH = 'length';
  var LAST_INDEX = 'lastIndex';
  if (
    'abbc'[$SPLIT](/(b)*/)[1] == 'c' ||
    'test'[$SPLIT](/(?:)/, -1)[LENGTH] != 4 ||
    'ab'[$SPLIT](/(?:ab)*/)[LENGTH] != 2 ||
    '.'[$SPLIT](/(.?)(.?)/)[LENGTH] != 4 ||
    '.'[$SPLIT](/()()/)[LENGTH] > 1 ||
    ''[$SPLIT](/.?/)[LENGTH]
  ) {
    var NPCG = /()??/.exec('')[1] === undefined; // nonparticipating capturing group
    // based on es5-shim implementation, need to rework it
    $split = function (separator, limit) {
      var string = String(this);
      if (separator === undefined && limit === 0) return [];
      // If `separator` is not a regex, use native split
      if (!isRegExp(separator)) return _split.call(string, separator, limit);
      var output = [];
      var flags = (separator.ignoreCase ? 'i' : '') +
                  (separator.multiline ? 'm' : '') +
                  (separator.unicode ? 'u' : '') +
                  (separator.sticky ? 'y' : '');
      var lastLastIndex = 0;
      var splitLimit = limit === undefined ? 4294967295 : limit >>> 0;
      // Make `global` and avoid `lastIndex` issues by working with a copy
      var separatorCopy = new RegExp(separator.source, flags + 'g');
      var separator2, match, lastIndex, lastLength, i;
      // Doesn't need flags gy, but they don't hurt
      if (!NPCG) separator2 = new RegExp('^' + separatorCopy.source + '$(?!\\s)', flags);
      while (match = separatorCopy.exec(string)) {
        // `separatorCopy.lastIndex` is not reliable cross-browser
        lastIndex = match.index + match[0][LENGTH];
        if (lastIndex > lastLastIndex) {
          output.push(string.slice(lastLastIndex, match.index));
          // Fix browsers whose `exec` methods don't consistently return `undefined` for NPCG
          // eslint-disable-next-line no-loop-func
          if (!NPCG && match[LENGTH] > 1) match[0].replace(separator2, function () {
            for (i = 1; i < arguments[LENGTH] - 2; i++) if (arguments[i] === undefined) match[i] = undefined;
          });
          if (match[LENGTH] > 1 && match.index < string[LENGTH]) $push.apply(output, match.slice(1));
          lastLength = match[0][LENGTH];
          lastLastIndex = lastIndex;
          if (output[LENGTH] >= splitLimit) break;
        }
        if (separatorCopy[LAST_INDEX] === match.index) separatorCopy[LAST_INDEX]++; // Avoid an infinite loop
      }
      if (lastLastIndex === string[LENGTH]) {
        if (lastLength || !separatorCopy.test('')) output.push('');
      } else output.push(string.slice(lastLastIndex));
      return output[LENGTH] > splitLimit ? output.slice(0, splitLimit) : output;
    };
  // Chakra, V8
  } else if ('0'[$SPLIT](undefined, 0)[LENGTH]) {
    $split = function (separator, limit) {
      return separator === undefined && limit === 0 ? [] : _split.call(this, separator, limit);
    };
  }
  // 21.1.3.17 String.prototype.split(separator, limit)
  return [function split(separator, limit) {
    var O = defined(this);
    var fn = separator == undefined ? undefined : separator[SPLIT];
    return fn !== undefined ? fn.call(separator, O, limit) : $split.call(String(O), separator, limit);
  }, $split];
});


/***/ }),
/* 115 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";

var strong = __webpack_require__(272);
var validate = __webpack_require__(41);
var SET = 'Set';

// 23.2 Set Objects
module.exports = __webpack_require__(57)(SET, function (get) {
  return function Set() { return get(this, arguments.length > 0 ? arguments[0] : undefined); };
}, {
  // 23.2.3.1 Set.prototype.add(value)
  add: function add(value) {
    return strong.def(validate(this, SET), value = value === 0 ? 0 : value, value);
  }
}, strong);


/***/ }),
/* 116 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";

var $export = __webpack_require__(1);
var $at = __webpack_require__(407)(false);
$export($export.P, 'String', {
  // 21.1.3.3 String.prototype.codePointAt(pos)
  codePointAt: function codePointAt(pos) {
    return $at(this, pos);
  }
});


/***/ }),
/* 117 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";
// 21.1.3.6 String.prototype.endsWith(searchString [, endPosition])

var $export = __webpack_require__(1);
var toLength = __webpack_require__(21);
var context = __webpack_require__(85);
var ENDS_WITH = 'endsWith';
var $endsWith = ''[ENDS_WITH];

$export($export.P + $export.F * __webpack_require__(77)(ENDS_WITH), 'String', {
  endsWith: function endsWith(searchString /* , endPosition = @length */) {
    var that = context(this, searchString, ENDS_WITH);
    var endPosition = arguments.length > 1 ? arguments[1] : undefined;
    var len = toLength(that.length);
    var end = endPosition === undefined ? len : Math.min(toLength(endPosition), len);
    var search = String(searchString);
    return $endsWith
      ? $endsWith.call(that, search, end)
      : that.slice(end - search.length, end) === search;
  }
});


/***/ }),
/* 118 */
/***/ (function(module, exports, __webpack_require__) {

var $export = __webpack_require__(1);
var toAbsoluteIndex = __webpack_require__(63);
var fromCharCode = String.fromCharCode;
var $fromCodePoint = String.fromCodePoint;

// length should be 1, old FF problem
$export($export.S + $export.F * (!!$fromCodePoint && $fromCodePoint.length != 1), 'String', {
  // 21.1.2.2 String.fromCodePoint(...codePoints)
  fromCodePoint: function fromCodePoint(x) { // eslint-disable-line no-unused-vars
    var res = [];
    var aLen = arguments.length;
    var i = 0;
    var code;
    while (aLen > i) {
      code = +arguments[i++];
      if (toAbsoluteIndex(code, 0x10ffff) !== code) throw RangeError(code + ' is not a valid code point');
      res.push(code < 0x10000
        ? fromCharCode(code)
        : fromCharCode(((code -= 0x10000) >> 10) + 0xd800, code % 0x400 + 0xdc00)
      );
    } return res.join('');
  }
});


/***/ }),
/* 119 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";
// 21.1.3.7 String.prototype.includes(searchString, position = 0)

var $export = __webpack_require__(1);
var context = __webpack_require__(85);
var INCLUDES = 'includes';

$export($export.P + $export.F * __webpack_require__(77)(INCLUDES), 'String', {
  includes: function includes(searchString /* , position = 0 */) {
    return !!~context(this, searchString, INCLUDES)
      .indexOf(searchString, arguments.length > 1 ? arguments[1] : undefined);
  }
});


/***/ }),
/* 120 */
/***/ (function(module, exports, __webpack_require__) {

var $export = __webpack_require__(1);
var toIObject = __webpack_require__(27);
var toLength = __webpack_require__(21);

$export($export.S, 'String', {
  // 21.1.2.4 String.raw(callSite, ...substitutions)
  raw: function raw(callSite) {
    var tpl = toIObject(callSite.raw);
    var len = toLength(tpl.length);
    var aLen = arguments.length;
    var res = [];
    var i = 0;
    while (len > i) {
      res.push(String(tpl[i++]));
      if (i < aLen) res.push(String(arguments[i]));
    } return res.join('');
  }
});


/***/ }),
/* 121 */
/***/ (function(module, exports, __webpack_require__) {

var $export = __webpack_require__(1);

$export($export.P, 'String', {
  // 21.1.3.13 String.prototype.repeat(count)
  repeat: __webpack_require__(290)
});


/***/ }),
/* 122 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";
// 21.1.3.18 String.prototype.startsWith(searchString [, position ])

var $export = __webpack_require__(1);
var toLength = __webpack_require__(21);
var context = __webpack_require__(85);
var STARTS_WITH = 'startsWith';
var $startsWith = ''[STARTS_WITH];

$export($export.P + $export.F * __webpack_require__(77)(STARTS_WITH), 'String', {
  startsWith: function startsWith(searchString /* , position = 0 */) {
    var that = context(this, searchString, STARTS_WITH);
    var index = toLength(Math.min(arguments.length > 1 ? arguments[1] : undefined, that.length));
    var search = String(searchString);
    return $startsWith
      ? $startsWith.call(that, search, index)
      : that.slice(index, index + search.length) === search;
  }
});


/***/ }),
/* 123 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";

// ECMAScript 6 symbols shim
var global = __webpack_require__(10);
var has = __webpack_require__(26);
var DESCRIPTORS = __webpack_require__(20);
var $export = __webpack_require__(1);
var redefine = __webpack_require__(32);
var META = __webpack_require__(47).KEY;
var $fails = __webpack_require__(25);
var shared = __webpack_require__(84);
var setToStringTag = __webpack_require__(50);
var uid = __webpack_require__(51);
var wks = __webpack_require__(8);
var wksExt = __webpack_require__(291);
var wksDefine = __webpack_require__(408);
var enumKeys = __webpack_require__(393);
var isArray = __webpack_require__(277);
var anObject = __webpack_require__(17);
var toIObject = __webpack_require__(27);
var toPrimitive = __webpack_require__(87);
var createDesc = __webpack_require__(49);
var _create = __webpack_require__(80);
var gOPNExt = __webpack_require__(400);
var $GOPD = __webpack_require__(81);
var $DP = __webpack_require__(18);
var $keys = __webpack_require__(39);
var gOPD = $GOPD.f;
var dP = $DP.f;
var gOPN = gOPNExt.f;
var $Symbol = global.Symbol;
var $JSON = global.JSON;
var _stringify = $JSON && $JSON.stringify;
var PROTOTYPE = 'prototype';
var HIDDEN = wks('_hidden');
var TO_PRIMITIVE = wks('toPrimitive');
var isEnum = {}.propertyIsEnumerable;
var SymbolRegistry = shared('symbol-registry');
var AllSymbols = shared('symbols');
var OPSymbols = shared('op-symbols');
var ObjectProto = Object[PROTOTYPE];
var USE_NATIVE = typeof $Symbol == 'function';
var QObject = global.QObject;
// Don't use setters in Qt Script, https://github.com/zloirock/core-js/issues/173
var setter = !QObject || !QObject[PROTOTYPE] || !QObject[PROTOTYPE].findChild;

// fallback for old Android, https://code.google.com/p/v8/issues/detail?id=687
var setSymbolDesc = DESCRIPTORS && $fails(function () {
  return _create(dP({}, 'a', {
    get: function () { return dP(this, 'a', { value: 7 }).a; }
  })).a != 7;
}) ? function (it, key, D) {
  var protoDesc = gOPD(ObjectProto, key);
  if (protoDesc) delete ObjectProto[key];
  dP(it, key, D);
  if (protoDesc && it !== ObjectProto) dP(ObjectProto, key, protoDesc);
} : dP;

var wrap = function (tag) {
  var sym = AllSymbols[tag] = _create($Symbol[PROTOTYPE]);
  sym._k = tag;
  return sym;
};

var isSymbol = USE_NATIVE && typeof $Symbol.iterator == 'symbol' ? function (it) {
  return typeof it == 'symbol';
} : function (it) {
  return it instanceof $Symbol;
};

var $defineProperty = function defineProperty(it, key, D) {
  if (it === ObjectProto) $defineProperty(OPSymbols, key, D);
  anObject(it);
  key = toPrimitive(key, true);
  anObject(D);
  if (has(AllSymbols, key)) {
    if (!D.enumerable) {
      if (!has(it, HIDDEN)) dP(it, HIDDEN, createDesc(1, {}));
      it[HIDDEN][key] = true;
    } else {
      if (has(it, HIDDEN) && it[HIDDEN][key]) it[HIDDEN][key] = false;
      D = _create(D, { enumerable: createDesc(0, false) });
    } return setSymbolDesc(it, key, D);
  } return dP(it, key, D);
};
var $defineProperties = function defineProperties(it, P) {
  anObject(it);
  var keys = enumKeys(P = toIObject(P));
  var i = 0;
  var l = keys.length;
  var key;
  while (l > i) $defineProperty(it, key = keys[i++], P[key]);
  return it;
};
var $create = function create(it, P) {
  return P === undefined ? _create(it) : $defineProperties(_create(it), P);
};
var $propertyIsEnumerable = function propertyIsEnumerable(key) {
  var E = isEnum.call(this, key = toPrimitive(key, true));
  if (this === ObjectProto && has(AllSymbols, key) && !has(OPSymbols, key)) return false;
  return E || !has(this, key) || !has(AllSymbols, key) || has(this, HIDDEN) && this[HIDDEN][key] ? E : true;
};
var $getOwnPropertyDescriptor = function getOwnPropertyDescriptor(it, key) {
  it = toIObject(it);
  key = toPrimitive(key, true);
  if (it === ObjectProto && has(AllSymbols, key) && !has(OPSymbols, key)) return;
  var D = gOPD(it, key);
  if (D && has(AllSymbols, key) && !(has(it, HIDDEN) && it[HIDDEN][key])) D.enumerable = true;
  return D;
};
var $getOwnPropertyNames = function getOwnPropertyNames(it) {
  var names = gOPN(toIObject(it));
  var result = [];
  var i = 0;
  var key;
  while (names.length > i) {
    if (!has(AllSymbols, key = names[i++]) && key != HIDDEN && key != META) result.push(key);
  } return result;
};
var $getOwnPropertySymbols = function getOwnPropertySymbols(it) {
  var IS_OP = it === ObjectProto;
  var names = gOPN(IS_OP ? OPSymbols : toIObject(it));
  var result = [];
  var i = 0;
  var key;
  while (names.length > i) {
    if (has(AllSymbols, key = names[i++]) && (IS_OP ? has(ObjectProto, key) : true)) result.push(AllSymbols[key]);
  } return result;
};

// 19.4.1.1 Symbol([description])
if (!USE_NATIVE) {
  $Symbol = function Symbol() {
    if (this instanceof $Symbol) throw TypeError('Symbol is not a constructor!');
    var tag = uid(arguments.length > 0 ? arguments[0] : undefined);
    var $set = function (value) {
      if (this === ObjectProto) $set.call(OPSymbols, value);
      if (has(this, HIDDEN) && has(this[HIDDEN], tag)) this[HIDDEN][tag] = false;
      setSymbolDesc(this, tag, createDesc(1, value));
    };
    if (DESCRIPTORS && setter) setSymbolDesc(ObjectProto, tag, { configurable: true, set: $set });
    return wrap(tag);
  };
  redefine($Symbol[PROTOTYPE], 'toString', function toString() {
    return this._k;
  });

  $GOPD.f = $getOwnPropertyDescriptor;
  $DP.f = $defineProperty;
  __webpack_require__(82).f = gOPNExt.f = $getOwnPropertyNames;
  __webpack_require__(48).f = $propertyIsEnumerable;
  __webpack_require__(61).f = $getOwnPropertySymbols;

  if (DESCRIPTORS && !__webpack_require__(60)) {
    redefine(ObjectProto, 'propertyIsEnumerable', $propertyIsEnumerable, true);
  }

  wksExt.f = function (name) {
    return wrap(wks(name));
  };
}

$export($export.G + $export.W + $export.F * !USE_NATIVE, { Symbol: $Symbol });

for (var es6Symbols = (
  // 19.4.2.2, 19.4.2.3, 19.4.2.4, 19.4.2.6, 19.4.2.8, 19.4.2.9, 19.4.2.10, 19.4.2.11, 19.4.2.12, 19.4.2.13, 19.4.2.14
  'hasInstance,isConcatSpreadable,iterator,match,replace,search,species,split,toPrimitive,toStringTag,unscopables'
).split(','), j = 0; es6Symbols.length > j;)wks(es6Symbols[j++]);

for (var wellKnownSymbols = $keys(wks.store), k = 0; wellKnownSymbols.length > k;) wksDefine(wellKnownSymbols[k++]);

$export($export.S + $export.F * !USE_NATIVE, 'Symbol', {
  // 19.4.2.1 Symbol.for(key)
  'for': function (key) {
    return has(SymbolRegistry, key += '')
      ? SymbolRegistry[key]
      : SymbolRegistry[key] = $Symbol(key);
  },
  // 19.4.2.5 Symbol.keyFor(sym)
  keyFor: function keyFor(sym) {
    if (!isSymbol(sym)) throw TypeError(sym + ' is not a symbol!');
    for (var key in SymbolRegistry) if (SymbolRegistry[key] === sym) return key;
  },
  useSetter: function () { setter = true; },
  useSimple: function () { setter = false; }
});

$export($export.S + $export.F * !USE_NATIVE, 'Object', {
  // 19.1.2.2 Object.create(O [, Properties])
  create: $create,
  // 19.1.2.4 Object.defineProperty(O, P, Attributes)
  defineProperty: $defineProperty,
  // 19.1.2.3 Object.defineProperties(O, Properties)
  defineProperties: $defineProperties,
  // 19.1.2.6 Object.getOwnPropertyDescriptor(O, P)
  getOwnPropertyDescriptor: $getOwnPropertyDescriptor,
  // 19.1.2.7 Object.getOwnPropertyNames(O)
  getOwnPropertyNames: $getOwnPropertyNames,
  // 19.1.2.8 Object.getOwnPropertySymbols(O)
  getOwnPropertySymbols: $getOwnPropertySymbols
});

// 24.3.2 JSON.stringify(value [, replacer [, space]])
$JSON && $export($export.S + $export.F * (!USE_NATIVE || $fails(function () {
  var S = $Symbol();
  // MS Edge converts symbol values to JSON as {}
  // WebKit converts symbol values to JSON as null
  // V8 throws on boxed symbols
  return _stringify([S]) != '[null]' || _stringify({ a: S }) != '{}' || _stringify(Object(S)) != '{}';
})), 'JSON', {
  stringify: function stringify(it) {
    if (it === undefined || isSymbol(it)) return; // IE8 returns string on undefined
    var args = [it];
    var i = 1;
    var replacer, $replacer;
    while (arguments.length > i) args.push(arguments[i++]);
    replacer = args[1];
    if (typeof replacer == 'function') $replacer = replacer;
    if ($replacer || !isArray(replacer)) replacer = function (key, value) {
      if ($replacer) value = $replacer.call(this, key, value);
      if (!isSymbol(value)) return value;
    };
    args[1] = replacer;
    return _stringify.apply($JSON, args);
  }
});

// 19.4.3.4 Symbol.prototype[@@toPrimitive](hint)
$Symbol[PROTOTYPE][TO_PRIMITIVE] || __webpack_require__(31)($Symbol[PROTOTYPE], TO_PRIMITIVE, $Symbol[PROTOTYPE].valueOf);
// 19.4.3.5 Symbol.prototype[@@toStringTag]
setToStringTag($Symbol, 'Symbol');
// 20.2.1.9 Math[@@toStringTag]
setToStringTag(Math, 'Math', true);
// 24.3.3 JSON[@@toStringTag]
setToStringTag(global.JSON, 'JSON', true);


/***/ }),
/* 124 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";

var each = __webpack_require__(56)(0);
var redefine = __webpack_require__(32);
var meta = __webpack_require__(47);
var assign = __webpack_require__(284);
var weak = __webpack_require__(273);
var isObject = __webpack_require__(12);
var fails = __webpack_require__(25);
var validate = __webpack_require__(41);
var WEAK_MAP = 'WeakMap';
var getWeak = meta.getWeak;
var isExtensible = Object.isExtensible;
var uncaughtFrozenStore = weak.ufstore;
var tmp = {};
var InternalMap;

var wrapper = function (get) {
  return function WeakMap() {
    return get(this, arguments.length > 0 ? arguments[0] : undefined);
  };
};

var methods = {
  // 23.3.3.3 WeakMap.prototype.get(key)
  get: function get(key) {
    if (isObject(key)) {
      var data = getWeak(key);
      if (data === true) return uncaughtFrozenStore(validate(this, WEAK_MAP)).get(key);
      return data ? data[this._i] : undefined;
    }
  },
  // 23.3.3.5 WeakMap.prototype.set(key, value)
  set: function set(key, value) {
    return weak.def(validate(this, WEAK_MAP), key, value);
  }
};

// 23.3 WeakMap Objects
var $WeakMap = module.exports = __webpack_require__(57)(WEAK_MAP, wrapper, methods, weak, true, true);

// IE11 WeakMap frozen keys fix
if (fails(function () { return new $WeakMap().set((Object.freeze || Object)(tmp), 7).get(tmp) != 7; })) {
  InternalMap = weak.getConstructor(wrapper, WEAK_MAP);
  assign(InternalMap.prototype, methods);
  meta.NEED = true;
  each(['delete', 'has', 'get', 'set'], function (key) {
    var proto = $WeakMap.prototype;
    var method = proto[key];
    redefine(proto, key, function (a, b) {
      // store frozen objects on internal weakmap shim
      if (isObject(a) && !isExtensible(a)) {
        if (!this._f) this._f = new InternalMap();
        var result = this._f[key](a, b);
        return key == 'set' ? this : result;
      // store all the rest on native weakmap
      } return method.call(this, a, b);
    });
  });
}


/***/ }),
/* 125 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";

var weak = __webpack_require__(273);
var validate = __webpack_require__(41);
var WEAK_SET = 'WeakSet';

// 23.4 WeakSet Objects
__webpack_require__(57)(WEAK_SET, function (get) {
  return function WeakSet() { return get(this, arguments.length > 0 ? arguments[0] : undefined); };
}, {
  // 23.4.3.1 WeakSet.prototype.add(value)
  add: function add(value) {
    return weak.def(validate(this, WEAK_SET), value, true);
  }
}, weak, false, true);


/***/ }),
/* 126 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";

// https://github.com/tc39/Array.prototype.includes
var $export = __webpack_require__(1);
var $includes = __webpack_require__(270)(true);

$export($export.P, 'Array', {
  includes: function includes(el /* , fromIndex = 0 */) {
    return $includes(this, el, arguments.length > 1 ? arguments[1] : undefined);
  }
});

__webpack_require__(37)('includes');


/***/ }),
/* 127 */
/***/ (function(module, exports, __webpack_require__) {

// https://github.com/tc39/proposal-object-values-entries
var $export = __webpack_require__(1);
var $entries = __webpack_require__(286)(true);

$export($export.S, 'Object', {
  entries: function entries(it) {
    return $entries(it);
  }
});


/***/ }),
/* 128 */
/***/ (function(module, exports, __webpack_require__) {

// https://github.com/tc39/proposal-object-getownpropertydescriptors
var $export = __webpack_require__(1);
var ownKeys = __webpack_require__(402);
var toIObject = __webpack_require__(27);
var gOPD = __webpack_require__(81);
var createProperty = __webpack_require__(74);

$export($export.S, 'Object', {
  getOwnPropertyDescriptors: function getOwnPropertyDescriptors(object) {
    var O = toIObject(object);
    var getDesc = gOPD.f;
    var keys = ownKeys(O);
    var result = {};
    var i = 0;
    var key, desc;
    while (keys.length > i) {
      desc = getDesc(O, key = keys[i++]);
      if (desc !== undefined) createProperty(result, key, desc);
    }
    return result;
  }
});


/***/ }),
/* 129 */
/***/ (function(module, exports, __webpack_require__) {

// https://github.com/tc39/proposal-object-values-entries
var $export = __webpack_require__(1);
var $values = __webpack_require__(286)(false);

$export($export.S, 'Object', {
  values: function values(it) {
    return $values(it);
  }
});


/***/ }),
/* 130 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";

// https://github.com/tc39/proposal-string-pad-start-end
var $export = __webpack_require__(1);
var $pad = __webpack_require__(289);

$export($export.P, 'String', {
  padEnd: function padEnd(maxLength /* , fillString = ' ' */) {
    return $pad(this, maxLength, arguments.length > 1 ? arguments[1] : undefined, false);
  }
});


/***/ }),
/* 131 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";

// https://github.com/tc39/proposal-string-pad-start-end
var $export = __webpack_require__(1);
var $pad = __webpack_require__(289);

$export($export.P, 'String', {
  padStart: function padStart(maxLength /* , fillString = ' ' */) {
    return $pad(this, maxLength, arguments.length > 1 ? arguments[1] : undefined, true);
  }
});


/***/ }),
/* 132 */
/***/ (function(module, exports, __webpack_require__) {

var $iterators = __webpack_require__(70);
var getKeys = __webpack_require__(39);
var redefine = __webpack_require__(32);
var global = __webpack_require__(10);
var hide = __webpack_require__(31);
var Iterators = __webpack_require__(46);
var wks = __webpack_require__(8);
var ITERATOR = wks('iterator');
var TO_STRING_TAG = wks('toStringTag');
var ArrayValues = Iterators.Array;

var DOMIterables = {
  CSSRuleList: true, // TODO: Not spec compliant, should be false.
  CSSStyleDeclaration: false,
  CSSValueList: false,
  ClientRectList: false,
  DOMRectList: false,
  DOMStringList: false,
  DOMTokenList: true,
  DataTransferItemList: false,
  FileList: false,
  HTMLAllCollection: false,
  HTMLCollection: false,
  HTMLFormElement: false,
  HTMLSelectElement: false,
  MediaList: true, // TODO: Not spec compliant, should be false.
  MimeTypeArray: false,
  NamedNodeMap: false,
  NodeList: true,
  PaintRequestList: false,
  Plugin: false,
  PluginArray: false,
  SVGLengthList: false,
  SVGNumberList: false,
  SVGPathSegList: false,
  SVGPointList: false,
  SVGStringList: false,
  SVGTransformList: false,
  SourceBufferList: false,
  StyleSheetList: true, // TODO: Not spec compliant, should be false.
  TextTrackCueList: false,
  TextTrackList: false,
  TouchList: false
};

for (var collections = getKeys(DOMIterables), i = 0; i < collections.length; i++) {
  var NAME = collections[i];
  var explicit = DOMIterables[NAME];
  var Collection = global[NAME];
  var proto = Collection && Collection.prototype;
  var key;
  if (proto) {
    if (!proto[ITERATOR]) hide(proto, ITERATOR, ArrayValues);
    if (!proto[TO_STRING_TAG]) hide(proto, TO_STRING_TAG, NAME);
    Iterators[NAME] = ArrayValues;
    if (explicit) for (key in $iterators) if (!proto[key]) redefine(proto, key, $iterators[key], true);
  }
}


/***/ }),
/* 133 */
/***/ (function(module, exports, __webpack_require__) {

var $export = __webpack_require__(1);
var $task = __webpack_require__(86);
$export($export.G + $export.B, {
  setImmediate: $task.set,
  clearImmediate: $task.clear
});


/***/ }),
/* 134 */
/***/ (function(module, exports) {



/***/ }),
/* 135 */
/***/ (function(module, exports) {



/***/ }),
/* 136 */
/***/ (function(module, exports) {



/***/ }),
/* 137 */
/***/ (function(module, exports) {



/***/ }),
/* 138 */
/***/ (function(module, exports) {



/***/ }),
/* 139 */
/***/ (function(module, exports) {



/***/ }),
/* 140 */
/***/ (function(module, exports) {



/***/ }),
/* 141 */
/***/ (function(module, exports) {



/***/ }),
/* 142 */
/***/ (function(module, exports) {



/***/ }),
/* 143 */
/***/ (function(module, exports) {



/***/ }),
/* 144 */
/***/ (function(module, exports) {



/***/ }),
/* 145 */
/***/ (function(module, exports) {



/***/ }),
/* 146 */
/***/ (function(module, exports) {



/***/ }),
/* 147 */
/***/ (function(module, exports) {



/***/ }),
/* 148 */
/***/ (function(module, exports) {



/***/ }),
/* 149 */
/***/ (function(module, exports) {



/***/ }),
/* 150 */
/***/ (function(module, exports) {



/***/ }),
/* 151 */
/***/ (function(module, exports) {



/***/ }),
/* 152 */
/***/ (function(module, exports) {



/***/ }),
/* 153 */
/***/ (function(module, exports) {



/***/ }),
/* 154 */
/***/ (function(module, exports) {



/***/ }),
/* 155 */
/***/ (function(module, exports) {



/***/ }),
/* 156 */
/***/ (function(module, exports) {



/***/ }),
/* 157 */
/***/ (function(module, exports) {



/***/ }),
/* 158 */
/***/ (function(module, exports) {



/***/ }),
/* 159 */
/***/ (function(module, exports) {



/***/ }),
/* 160 */
/***/ (function(module, exports) {



/***/ }),
/* 161 */
/***/ (function(module, exports) {



/***/ }),
/* 162 */
/***/ (function(module, exports) {



/***/ }),
/* 163 */
/***/ (function(module, exports) {



/***/ }),
/* 164 */
/***/ (function(module, exports) {



/***/ }),
/* 165 */
/***/ (function(module, exports) {



/***/ }),
/* 166 */
/***/ (function(module, exports) {



/***/ }),
/* 167 */
/***/ (function(module, exports) {



/***/ }),
/* 168 */
/***/ (function(module, exports) {



/***/ }),
/* 169 */
/***/ (function(module, exports) {



/***/ }),
/* 170 */
/***/ (function(module, exports) {



/***/ }),
/* 171 */
/***/ (function(module, exports) {



/***/ }),
/* 172 */
/***/ (function(module, exports) {



/***/ }),
/* 173 */
/***/ (function(module, exports) {



/***/ }),
/* 174 */
/***/ (function(module, exports) {



/***/ }),
/* 175 */
/***/ (function(module, exports) {



/***/ }),
/* 176 */
/***/ (function(module, exports) {



/***/ }),
/* 177 */
/***/ (function(module, exports) {



/***/ }),
/* 178 */
/***/ (function(module, exports) {



/***/ }),
/* 179 */
/***/ (function(module, exports) {



/***/ }),
/* 180 */
/***/ (function(module, exports) {



/***/ }),
/* 181 */
/***/ (function(module, exports) {



/***/ }),
/* 182 */
/***/ (function(module, exports) {



/***/ }),
/* 183 */
/***/ (function(module, exports) {



/***/ }),
/* 184 */
/***/ (function(module, exports) {



/***/ }),
/* 185 */
/***/ (function(module, exports) {



/***/ }),
/* 186 */
/***/ (function(module, exports) {



/***/ }),
/* 187 */
/***/ (function(module, exports) {



/***/ }),
/* 188 */
/***/ (function(module, exports) {



/***/ }),
/* 189 */
/***/ (function(module, exports) {



/***/ }),
/* 190 */
/***/ (function(module, exports) {



/***/ }),
/* 191 */
/***/ (function(module, exports) {



/***/ }),
/* 192 */
/***/ (function(module, exports) {



/***/ }),
/* 193 */
/***/ (function(module, exports) {



/***/ }),
/* 194 */
/***/ (function(module, exports) {



/***/ }),
/* 195 */
/***/ (function(module, exports) {



/***/ }),
/* 196 */
/***/ (function(module, exports) {



/***/ }),
/* 197 */
/***/ (function(module, exports) {



/***/ }),
/* 198 */
/***/ (function(module, exports) {



/***/ }),
/* 199 */
/***/ (function(module, exports) {



/***/ }),
/* 200 */
/***/ (function(module, exports) {



/***/ }),
/* 201 */
/***/ (function(module, exports) {



/***/ }),
/* 202 */
/***/ (function(module, exports) {



/***/ }),
/* 203 */
/***/ (function(module, exports) {



/***/ }),
/* 204 */
/***/ (function(module, exports) {



/***/ }),
/* 205 */
/***/ (function(module, exports) {



/***/ }),
/* 206 */
/***/ (function(module, exports) {



/***/ }),
/* 207 */
/***/ (function(module, exports) {



/***/ }),
/* 208 */
/***/ (function(module, exports) {



/***/ }),
/* 209 */
/***/ (function(module, exports) {



/***/ }),
/* 210 */
/***/ (function(module, exports) {



/***/ }),
/* 211 */
/***/ (function(module, exports) {



/***/ }),
/* 212 */
/***/ (function(module, exports) {



/***/ }),
/* 213 */
/***/ (function(module, exports) {



/***/ }),
/* 214 */
/***/ (function(module, exports) {



/***/ }),
/* 215 */
/***/ (function(module, exports) {



/***/ }),
/* 216 */
/***/ (function(module, exports) {



/***/ }),
/* 217 */
/***/ (function(module, exports) {



/***/ }),
/* 218 */
/***/ (function(module, exports) {



/***/ }),
/* 219 */
/***/ (function(module, exports) {



/***/ }),
/* 220 */
/***/ (function(module, exports) {



/***/ }),
/* 221 */
/***/ (function(module, exports) {



/***/ }),
/* 222 */
/***/ (function(module, exports) {



/***/ }),
/* 223 */
/***/ (function(module, exports) {



/***/ }),
/* 224 */
/***/ (function(module, exports) {



/***/ }),
/* 225 */
/***/ (function(module, exports) {



/***/ }),
/* 226 */
/***/ (function(module, exports) {



/***/ }),
/* 227 */
/***/ (function(module, exports) {



/***/ }),
/* 228 */
/***/ (function(module, exports) {



/***/ }),
/* 229 */
/***/ (function(module, exports) {



/***/ }),
/* 230 */
/***/ (function(module, exports) {



/***/ }),
/* 231 */
/***/ (function(module, exports) {



/***/ }),
/* 232 */
/***/ (function(module, exports) {



/***/ }),
/* 233 */
/***/ (function(module, exports) {



/***/ }),
/* 234 */
/***/ (function(module, exports) {



/***/ }),
/* 235 */
/***/ (function(module, exports) {



/***/ }),
/* 236 */
/***/ (function(module, exports) {



/***/ }),
/* 237 */
/***/ (function(module, exports) {



/***/ }),
/* 238 */
/***/ (function(module, exports) {



/***/ }),
/* 239 */
/***/ (function(module, exports) {



/***/ }),
/* 240 */
/***/ (function(module, exports) {



/***/ }),
/* 241 */
/***/ (function(module, exports) {



/***/ }),
/* 242 */
/***/ (function(module, exports) {



/***/ }),
/* 243 */
/***/ (function(module, exports) {



/***/ }),
/* 244 */
/***/ (function(module, exports) {



/***/ }),
/* 245 */
/***/ (function(module, exports) {



/***/ }),
/* 246 */
/***/ (function(module, exports) {



/***/ }),
/* 247 */
/***/ (function(module, exports) {



/***/ }),
/* 248 */
/***/ (function(module, exports) {



/***/ }),
/* 249 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


/**
 * SheetClip - Spreadsheet Clipboard Parser
 * version 0.2
 *
 * This tiny library transforms JavaScript arrays to strings that are pasteable by LibreOffice, OpenOffice,
 * Google Docs and Microsoft Excel.
 *
 * Copyright 2012, Marcin Warpechowski
 * Licensed under the MIT license.
 * http://github.com/warpech/sheetclip/
 */
/*jslint white: true*/
(function (global) {
  "use strict";

  function countQuotes(str) {
    return str.split('"').length - 1;
  }

  var SheetClip = {
    /**
     * Decode spreadsheet string into array
     *
     * @param {String} str
     * @returns {Array}
     */
    parse: function parse(str) {
      var r,
          rLen,
          rows,
          arr = [],
          a = 0,
          c,
          cLen,
          multiline,
          last;

      rows = str.split('\n');

      if (rows.length > 1 && rows[rows.length - 1] === '') {
        rows.pop();
      }
      for (r = 0, rLen = rows.length; r < rLen; r += 1) {
        rows[r] = rows[r].split('\t');

        for (c = 0, cLen = rows[r].length; c < cLen; c += 1) {
          if (!arr[a]) {
            arr[a] = [];
          }
          if (multiline && c === 0) {
            last = arr[a].length - 1;
            arr[a][last] = arr[a][last] + '\n' + rows[r][0];

            if (multiline && countQuotes(rows[r][0]) & 1) {
              //& 1 is a bitwise way of performing mod 2
              multiline = false;
              arr[a][last] = arr[a][last].substring(0, arr[a][last].length - 1).replace(/""/g, '"');
            }
          } else {
            if (c === cLen - 1 && rows[r][c].indexOf('"') === 0 && countQuotes(rows[r][c]) & 1) {
              arr[a].push(rows[r][c].substring(1).replace(/""/g, '"'));
              multiline = true;
            } else {
              arr[a].push(rows[r][c].replace(/""/g, '"'));
              multiline = false;
            }
          }
        }
        if (!multiline) {
          a += 1;
        }
      }

      return arr;
    },

    /**
     * Encode array into valid spreadsheet string
     *
     * @param arr
     * @returns {String}
     */
    stringify: function stringify(arr) {
      var r,
          rLen,
          c,
          cLen,
          str = '',
          val;

      for (r = 0, rLen = arr.length; r < rLen; r += 1) {
        cLen = arr[r].length;

        for (c = 0; c < cLen; c += 1) {
          if (c > 0) {
            str += '\t';
          }
          val = arr[r][c];

          if (typeof val === 'string') {
            if (val.indexOf('\n') > -1) {
              str += '"' + val.replace(/"/g, '""') + '"';
            } else {
              str += val;
            }
          } else if (val === null || val === void 0) {
            // void 0 resolves to undefined
            str += '';
          } else {
            str += val;
          }
        }

        if (r !== rLen - 1) {
          str += '\n';
        }
      }

      return str;
    }
  };

  if (true) {
    exports.parse = SheetClip.parse;
    exports.stringify = SheetClip.stringify;
  } else {
    global.SheetClip = SheetClip;
  }
})(window);

/***/ }),
/* 250 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


exports.__esModule = true;

var _createClass = 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); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

var _element = __webpack_require__(0);

var _event = __webpack_require__(7);

var _object = __webpack_require__(3);

var _browser = __webpack_require__(22);

var _eventManager = __webpack_require__(4);

var _eventManager2 = _interopRequireDefault(_eventManager);

var _coords = __webpack_require__(43);

var _coords2 = _interopRequireDefault(_coords);

var _base = __webpack_require__(29);

var _base2 = _interopRequireDefault(_base);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

/**
 *
 */
var Border = function () {
  /**
   * @param {Walkontable} wotInstance
   * @param {Object} settings
   */
  function Border(wotInstance, settings) {
    _classCallCheck(this, Border);

    if (!settings) {
      return;
    }
    this.eventManager = new _eventManager2.default(wotInstance);
    this.instance = wotInstance;
    this.wot = wotInstance;
    this.settings = settings;
    this.mouseDown = false;
    this.main = null;

    this.top = null;
    this.left = null;
    this.bottom = null;
    this.right = null;

    this.topStyle = null;
    this.leftStyle = null;
    this.bottomStyle = null;
    this.rightStyle = null;

    this.cornerDefaultStyle = {
      width: '5px',
      height: '5px',
      borderWidth: '2px',
      borderStyle: 'solid',
      borderColor: '#FFF'
    };
    this.corner = null;
    this.cornerStyle = null;

    this.createBorders(settings);
    this.registerListeners();
  }

  /**
   * Register all necessary events
   */


  _createClass(Border, [{
    key: 'registerListeners',
    value: function registerListeners() {
      var _this2 = this;

      this.eventManager.addEventListener(document.body, 'mousedown', function () {
        return _this2.onMouseDown();
      });
      this.eventManager.addEventListener(document.body, 'mouseup', function () {
        return _this2.onMouseUp();
      });

      var _loop = function _loop(c, len) {
        _this2.eventManager.addEventListener(_this2.main.childNodes[c], 'mouseenter', function (event) {
          return _this2.onMouseEnter(event, _this2.main.childNodes[c]);
        });
      };

      for (var c = 0, len = this.main.childNodes.length; c < len; c++) {
        _loop(c, len);
      }
    }

    /**
     * Mouse down listener
     *
     * @private
     */

  }, {
    key: 'onMouseDown',
    value: function onMouseDown() {
      this.mouseDown = true;
    }

    /**
     * Mouse up listener
     *
     * @private
     */

  }, {
    key: 'onMouseUp',
    value: function onMouseUp() {
      this.mouseDown = false;
    }

    /**
     * Mouse enter listener for fragment selection functionality.
     *
     * @private
     * @param {Event} event Dom event
     * @param {HTMLElement} parentElement Part of border element.
     */

  }, {
    key: 'onMouseEnter',
    value: function onMouseEnter(event, parentElement) {
      if (!this.mouseDown || !this.wot.getSetting('hideBorderOnMouseDownOver')) {
        return;
      }
      event.preventDefault();
      (0, _event.stopImmediatePropagation)(event);

      var _this = this;
      var bounds = parentElement.getBoundingClientRect();
      // Hide border to prevents selection jumping when fragmentSelection is enabled.
      parentElement.style.display = 'none';

      function isOutside(event) {
        if (event.clientY < Math.floor(bounds.top)) {
          return true;
        }
        if (event.clientY > Math.ceil(bounds.top + bounds.height)) {
          return true;
        }
        if (event.clientX < Math.floor(bounds.left)) {
          return true;
        }
        if (event.clientX > Math.ceil(bounds.left + bounds.width)) {
          return true;
        }
      }

      function handler(event) {
        if (isOutside(event)) {
          _this.eventManager.removeEventListener(document.body, 'mousemove', handler);
          parentElement.style.display = 'block';
        }
      }

      this.eventManager.addEventListener(document.body, 'mousemove', handler);
    }

    /**
     * Create border elements
     *
     * @param {Object} settings
     */

  }, {
    key: 'createBorders',
    value: function createBorders(settings) {
      this.main = document.createElement('div');

      var borderDivs = ['top', 'left', 'bottom', 'right', 'corner'];
      var style = this.main.style;
      style.position = 'absolute';
      style.top = 0;
      style.left = 0;

      for (var i = 0; i < 5; i++) {
        var position = borderDivs[i];
        var div = document.createElement('div');
        div.className = 'wtBorder ' + (this.settings.className || ''); // + borderDivs[i];

        if (this.settings[position] && this.settings[position].hide) {
          div.className += ' hidden';
        }
        style = div.style;
        style.backgroundColor = this.settings[position] && this.settings[position].color ? this.settings[position].color : settings.border.color;
        style.height = this.settings[position] && this.settings[position].width ? this.settings[position].width + 'px' : settings.border.width + 'px';
        style.width = this.settings[position] && this.settings[position].width ? this.settings[position].width + 'px' : settings.border.width + 'px';

        this.main.appendChild(div);
      }
      this.top = this.main.childNodes[0];
      this.left = this.main.childNodes[1];
      this.bottom = this.main.childNodes[2];
      this.right = this.main.childNodes[3];

      this.topStyle = this.top.style;
      this.leftStyle = this.left.style;
      this.bottomStyle = this.bottom.style;
      this.rightStyle = this.right.style;

      this.corner = this.main.childNodes[4];
      this.corner.className += ' corner';
      this.cornerStyle = this.corner.style;
      this.cornerStyle.width = this.cornerDefaultStyle.width;
      this.cornerStyle.height = this.cornerDefaultStyle.height;
      this.cornerStyle.border = [this.cornerDefaultStyle.borderWidth, this.cornerDefaultStyle.borderStyle, this.cornerDefaultStyle.borderColor].join(' ');

      if ((0, _browser.isMobileBrowser)()) {
        this.createMultipleSelectorHandles();
      }
      this.disappear();

      if (!this.wot.wtTable.bordersHolder) {
        this.wot.wtTable.bordersHolder = document.createElement('div');
        this.wot.wtTable.bordersHolder.className = 'htBorders';
        this.wot.wtTable.spreader.appendChild(this.wot.wtTable.bordersHolder);
      }
      this.wot.wtTable.bordersHolder.insertBefore(this.main, this.wot.wtTable.bordersHolder.firstChild);
    }

    /**
     * Create multiple selector handler for mobile devices
     */

  }, {
    key: 'createMultipleSelectorHandles',
    value: function createMultipleSelectorHandles() {
      this.selectionHandles = {
        topLeft: document.createElement('DIV'),
        topLeftHitArea: document.createElement('DIV'),
        bottomRight: document.createElement('DIV'),
        bottomRightHitArea: document.createElement('DIV')
      };
      var width = 10;
      var hitAreaWidth = 40;

      this.selectionHandles.topLeft.className = 'topLeftSelectionHandle';
      this.selectionHandles.topLeftHitArea.className = 'topLeftSelectionHandle-HitArea';
      this.selectionHandles.bottomRight.className = 'bottomRightSelectionHandle';
      this.selectionHandles.bottomRightHitArea.className = 'bottomRightSelectionHandle-HitArea';

      this.selectionHandles.styles = {
        topLeft: this.selectionHandles.topLeft.style,
        topLeftHitArea: this.selectionHandles.topLeftHitArea.style,
        bottomRight: this.selectionHandles.bottomRight.style,
        bottomRightHitArea: this.selectionHandles.bottomRightHitArea.style
      };

      var hitAreaStyle = {
        position: 'absolute',
        height: hitAreaWidth + 'px',
        width: hitAreaWidth + 'px',
        'border-radius': parseInt(hitAreaWidth / 1.5, 10) + 'px'
      };

      for (var prop in hitAreaStyle) {
        if ((0, _object.hasOwnProperty)(hitAreaStyle, prop)) {
          this.selectionHandles.styles.bottomRightHitArea[prop] = hitAreaStyle[prop];
          this.selectionHandles.styles.topLeftHitArea[prop] = hitAreaStyle[prop];
        }
      }

      var handleStyle = {
        position: 'absolute',
        height: width + 'px',
        width: width + 'px',
        'border-radius': parseInt(width / 1.5, 10) + 'px',
        background: '#F5F5FF',
        border: '1px solid #4285c8'
      };

      for (var _prop in handleStyle) {
        if ((0, _object.hasOwnProperty)(handleStyle, _prop)) {
          this.selectionHandles.styles.bottomRight[_prop] = handleStyle[_prop];
          this.selectionHandles.styles.topLeft[_prop] = handleStyle[_prop];
        }
      }
      this.main.appendChild(this.selectionHandles.topLeft);
      this.main.appendChild(this.selectionHandles.bottomRight);
      this.main.appendChild(this.selectionHandles.topLeftHitArea);
      this.main.appendChild(this.selectionHandles.bottomRightHitArea);
    }
  }, {
    key: 'isPartRange',
    value: function isPartRange(row, col) {
      if (this.wot.selections.area.cellRange) {
        if (row != this.wot.selections.area.cellRange.to.row || col != this.wot.selections.area.cellRange.to.col) {
          return true;
        }
      }

      return false;
    }
  }, {
    key: 'updateMultipleSelectionHandlesPosition',
    value: function updateMultipleSelectionHandlesPosition(row, col, top, left, width, height) {
      var handleWidth = parseInt(this.selectionHandles.styles.topLeft.width, 10);
      var hitAreaWidth = parseInt(this.selectionHandles.styles.topLeftHitArea.width, 10);

      this.selectionHandles.styles.topLeft.top = parseInt(top - handleWidth, 10) + 'px';
      this.selectionHandles.styles.topLeft.left = parseInt(left - handleWidth, 10) + 'px';

      this.selectionHandles.styles.topLeftHitArea.top = parseInt(top - hitAreaWidth / 4 * 3, 10) + 'px';
      this.selectionHandles.styles.topLeftHitArea.left = parseInt(left - hitAreaWidth / 4 * 3, 10) + 'px';

      this.selectionHandles.styles.bottomRight.top = parseInt(top + height, 10) + 'px';
      this.selectionHandles.styles.bottomRight.left = parseInt(left + width, 10) + 'px';

      this.selectionHandles.styles.bottomRightHitArea.top = parseInt(top + height - hitAreaWidth / 4, 10) + 'px';
      this.selectionHandles.styles.bottomRightHitArea.left = parseInt(left + width - hitAreaWidth / 4, 10) + 'px';

      if (this.settings.border.multipleSelectionHandlesVisible && this.settings.border.multipleSelectionHandlesVisible()) {
        this.selectionHandles.styles.topLeft.display = 'block';
        this.selectionHandles.styles.topLeftHitArea.display = 'block';

        if (this.isPartRange(row, col)) {
          this.selectionHandles.styles.bottomRight.display = 'none';
          this.selectionHandles.styles.bottomRightHitArea.display = 'none';
        } else {
          this.selectionHandles.styles.bottomRight.display = 'block';
          this.selectionHandles.styles.bottomRightHitArea.display = 'block';
        }
      } else {
        this.selectionHandles.styles.topLeft.display = 'none';
        this.selectionHandles.styles.bottomRight.display = 'none';
        this.selectionHandles.styles.topLeftHitArea.display = 'none';
        this.selectionHandles.styles.bottomRightHitArea.display = 'none';
      }

      if (row == this.wot.wtSettings.getSetting('fixedRowsTop') || col == this.wot.wtSettings.getSetting('fixedColumnsLeft')) {
        this.selectionHandles.styles.topLeft.zIndex = '9999';
        this.selectionHandles.styles.topLeftHitArea.zIndex = '9999';
      } else {
        this.selectionHandles.styles.topLeft.zIndex = '';
        this.selectionHandles.styles.topLeftHitArea.zIndex = '';
      }
    }

    /**
     * Show border around one or many cells
     *
     * @param {Array} corners
     */

  }, {
    key: 'appear',
    value: function appear(corners) {
      if (this.disabled) {
        return;
      }
      var isMultiple, fromTD, toTD, fromOffset, toOffset, containerOffset, top, minTop, left, minLeft, height, width, fromRow, fromColumn, toRow, toColumn, trimmingContainer, cornerOverlappingContainer, ilen;

      ilen = this.wot.wtTable.getRenderedRowsCount();

      for (var i = 0; i < ilen; i++) {
        var s = this.wot.wtTable.rowFilter.renderedToSource(i);

        if (s >= corners[0] && s <= corners[2]) {
          fromRow = s;
          break;
        }
      }

      for (var _i = ilen - 1; _i >= 0; _i--) {
        var _s = this.wot.wtTable.rowFilter.renderedToSource(_i);

        if (_s >= corners[0] && _s <= corners[2]) {
          toRow = _s;
          break;
        }
      }

      ilen = this.wot.wtTable.getRenderedColumnsCount();

      for (var _i2 = 0; _i2 < ilen; _i2++) {
        var _s2 = this.wot.wtTable.columnFilter.renderedToSource(_i2);

        if (_s2 >= corners[1] && _s2 <= corners[3]) {
          fromColumn = _s2;
          break;
        }
      }

      for (var _i3 = ilen - 1; _i3 >= 0; _i3--) {
        var _s3 = this.wot.wtTable.columnFilter.renderedToSource(_i3);

        if (_s3 >= corners[1] && _s3 <= corners[3]) {
          toColumn = _s3;
          break;
        }
      }
      if (fromRow === void 0 || fromColumn === void 0) {
        this.disappear();

        return;
      }
      isMultiple = fromRow !== toRow || fromColumn !== toColumn;
      fromTD = this.wot.wtTable.getCell(new _coords2.default(fromRow, fromColumn));
      toTD = isMultiple ? this.wot.wtTable.getCell(new _coords2.default(toRow, toColumn)) : fromTD;
      fromOffset = (0, _element.offset)(fromTD);
      toOffset = isMultiple ? (0, _element.offset)(toTD) : fromOffset;
      containerOffset = (0, _element.offset)(this.wot.wtTable.TABLE);

      minTop = fromOffset.top;
      height = toOffset.top + (0, _element.outerHeight)(toTD) - minTop;
      minLeft = fromOffset.left;
      width = toOffset.left + (0, _element.outerWidth)(toTD) - minLeft;

      top = minTop - containerOffset.top - 1;
      left = minLeft - containerOffset.left - 1;
      var style = (0, _element.getComputedStyle)(fromTD);

      if (parseInt(style.borderTopWidth, 10) > 0) {
        top += 1;
        height = height > 0 ? height - 1 : 0;
      }
      if (parseInt(style.borderLeftWidth, 10) > 0) {
        left += 1;
        width = width > 0 ? width - 1 : 0;
      }

      this.topStyle.top = top + 'px';
      this.topStyle.left = left + 'px';
      this.topStyle.width = width + 'px';
      this.topStyle.display = 'block';

      this.leftStyle.top = top + 'px';
      this.leftStyle.left = left + 'px';
      this.leftStyle.height = height + 'px';
      this.leftStyle.display = 'block';

      var delta = Math.floor(this.settings.border.width / 2);

      this.bottomStyle.top = top + height - delta + 'px';
      this.bottomStyle.left = left + 'px';
      this.bottomStyle.width = width + 'px';
      this.bottomStyle.display = 'block';

      this.rightStyle.top = top + 'px';
      this.rightStyle.left = left + width - delta + 'px';
      this.rightStyle.height = height + 1 + 'px';
      this.rightStyle.display = 'block';

      if ((0, _browser.isMobileBrowser)() || !this.hasSetting(this.settings.border.cornerVisible) || this.isPartRange(toRow, toColumn)) {
        this.cornerStyle.display = 'none';
      } else {
        this.cornerStyle.top = top + height - 4 + 'px';
        this.cornerStyle.left = left + width - 4 + 'px';
        this.cornerStyle.borderRightWidth = this.cornerDefaultStyle.borderWidth;
        this.cornerStyle.width = this.cornerDefaultStyle.width;

        // Hide the fill handle, so the possible further adjustments won't force unneeded scrollbars.
        this.cornerStyle.display = 'none';

        trimmingContainer = (0, _element.getTrimmingContainer)(this.wot.wtTable.TABLE);

        if (toColumn === this.wot.getSetting('totalColumns') - 1) {
          cornerOverlappingContainer = toTD.offsetLeft + (0, _element.outerWidth)(toTD) + parseInt(this.cornerDefaultStyle.width, 10) / 2 >= (0, _element.innerWidth)(trimmingContainer);

          if (cornerOverlappingContainer) {
            this.cornerStyle.left = Math.floor(left + width - 3 - parseInt(this.cornerDefaultStyle.width, 10) / 2) + 'px';
            this.cornerStyle.borderRightWidth = 0;
          }
        }

        if (toRow === this.wot.getSetting('totalRows') - 1) {
          cornerOverlappingContainer = toTD.offsetTop + (0, _element.outerHeight)(toTD) + parseInt(this.cornerDefaultStyle.height, 10) / 2 >= (0, _element.innerHeight)(trimmingContainer);

          if (cornerOverlappingContainer) {
            this.cornerStyle.top = Math.floor(top + height - 3 - parseInt(this.cornerDefaultStyle.height, 10) / 2) + 'px';
            this.cornerStyle.borderBottomWidth = 0;
          }
        }

        this.cornerStyle.display = 'block';
      }

      if ((0, _browser.isMobileBrowser)()) {
        this.updateMultipleSelectionHandlesPosition(fromRow, fromColumn, top, left, width, height);
      }
    }

    /**
     * Hide border
     */

  }, {
    key: 'disappear',
    value: function disappear() {
      this.topStyle.display = 'none';
      this.leftStyle.display = 'none';
      this.bottomStyle.display = 'none';
      this.rightStyle.display = 'none';
      this.cornerStyle.display = 'none';

      if ((0, _browser.isMobileBrowser)()) {
        this.selectionHandles.styles.topLeft.display = 'none';
        this.selectionHandles.styles.bottomRight.display = 'none';
      }
    }

    /**
     * @param {Function} setting
     * @returns {*}
     */

  }, {
    key: 'hasSetting',
    value: function hasSetting(setting) {
      if (typeof setting === 'function') {
        return setting();
      }

      return !!setting;
    }
  }]);

  return Border;
}();

exports.default = Border;

/***/ }),
/* 251 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


exports.__esModule = true;

var _createClass = 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); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

var privatePool = new WeakMap();

/**
 * Calculates indexes of columns to render OR columns that are visible.
 * To redo the calculation, you need to create a new calculator.
 *
 * @class ViewportColumnsCalculator
 */

var ViewportColumnsCalculator = function () {
  _createClass(ViewportColumnsCalculator, null, [{
    key: 'DEFAULT_WIDTH',

    /**
     * Default column width
     *
     * @type {Number}
     */
    get: function get() {
      return 50;
    }

    /**
     * @param {Number} viewportWidth Width of the viewport
     * @param {Number} scrollOffset Current horizontal scroll position of the viewport
     * @param {Number} totalColumns Total number of rows
     * @param {Function} columnWidthFn Function that returns the width of the column at a given index (in px)
     * @param {Function} overrideFn Function that changes calculated this.startRow, this.endRow (used by MergeCells plugin)
     * @param {Boolean} onlyFullyVisible if `true`, only startRow and endRow will be indexes of rows that are fully in viewport
     * @param {Boolean} stretchH
     * @param {Function} [stretchingColumnWidthFn] Function that returns the new width of the stretched column.
     */

  }]);

  function ViewportColumnsCalculator(viewportWidth, scrollOffset, totalColumns, columnWidthFn, overrideFn, onlyFullyVisible, stretchH) {
    var stretchingColumnWidthFn = arguments.length > 7 && arguments[7] !== undefined ? arguments[7] : function (width) {
      return width;
    };

    _classCallCheck(this, ViewportColumnsCalculator);

    privatePool.set(this, {
      viewportWidth: viewportWidth,
      scrollOffset: scrollOffset,
      totalColumns: totalColumns,
      columnWidthFn: columnWidthFn,
      overrideFn: overrideFn,
      onlyFullyVisible: onlyFullyVisible,
      stretchingColumnWidthFn: stretchingColumnWidthFn
    });

    /**
     * Number of rendered/visible columns
     *
     * @type {Number}
     */
    this.count = 0;

    /**
     * Index of the first rendered/visible column (can be overwritten using overrideFn)
     *
     * @type {Number|null}
     */
    this.startColumn = null;

    /**
     * Index of the last rendered/visible column (can be overwritten using overrideFn)
     *
     * @type {null}
     */
    this.endColumn = null;

    /**
     * Position of the first rendered/visible column (in px)
     *
     * @type {Number|null}
     */
    this.startPosition = null;

    this.stretchAllRatio = 0;
    this.stretchLastWidth = 0;
    this.stretch = stretchH;
    this.totalTargetWidth = 0;
    this.needVerifyLastColumnWidth = true;
    this.stretchAllColumnsWidth = [];

    this.calculate();
  }

  /**
   * Calculates viewport
   */


  _createClass(ViewportColumnsCalculator, [{
    key: 'calculate',
    value: function calculate() {
      var sum = 0;
      var needReverse = true;
      var startPositions = [];
      var columnWidth = void 0;

      var priv = privatePool.get(this);
      var onlyFullyVisible = priv.onlyFullyVisible;
      var overrideFn = priv.overrideFn;
      var scrollOffset = priv.scrollOffset;
      var totalColumns = priv.totalColumns;
      var viewportWidth = priv.viewportWidth;

      for (var i = 0; i < totalColumns; i++) {
        columnWidth = this._getColumnWidth(i);

        if (sum <= scrollOffset && !onlyFullyVisible) {
          this.startColumn = i;
        }

        // +1 pixel for row header width compensation for horizontal scroll > 0
        var compensatedViewportWidth = scrollOffset > 0 ? viewportWidth + 1 : viewportWidth;

        if (sum >= scrollOffset && sum + columnWidth <= scrollOffset + compensatedViewportWidth) {
          if (this.startColumn == null) {
            this.startColumn = i;
          }
          this.endColumn = i;
        }
        startPositions.push(sum);
        sum += columnWidth;

        if (!onlyFullyVisible) {
          this.endColumn = i;
        }
        if (sum >= scrollOffset + viewportWidth) {
          needReverse = false;
          break;
        }
      }

      if (this.endColumn === totalColumns - 1 && needReverse) {
        this.startColumn = this.endColumn;

        while (this.startColumn > 0) {
          var viewportSum = startPositions[this.endColumn] + columnWidth - startPositions[this.startColumn - 1];

          if (viewportSum <= viewportWidth || !onlyFullyVisible) {
            this.startColumn--;
          }
          if (viewportSum > viewportWidth) {
            break;
          }
        }
      }

      if (this.startColumn !== null && overrideFn) {
        overrideFn(this);
      }
      this.startPosition = startPositions[this.startColumn];

      if (this.startPosition == void 0) {
        this.startPosition = null;
      }
      if (this.startColumn !== null) {
        this.count = this.endColumn - this.startColumn + 1;
      }
    }

    /**
     * Recalculate columns stretching.
     *
     * @param {Number} totalWidth
     */

  }, {
    key: 'refreshStretching',
    value: function refreshStretching(totalWidth) {
      if (this.stretch === 'none') {
        return;
      }
      this.totalTargetWidth = totalWidth;

      var priv = privatePool.get(this);
      var totalColumns = priv.totalColumns;
      var sumAll = 0;

      for (var i = 0; i < totalColumns; i++) {
        var columnWidth = this._getColumnWidth(i);
        var permanentColumnWidth = priv.stretchingColumnWidthFn(void 0, i);

        if (typeof permanentColumnWidth === 'number') {
          totalWidth -= permanentColumnWidth;
        } else {
          sumAll += columnWidth;
        }
      }
      var remainingSize = totalWidth - sumAll;

      if (this.stretch === 'all' && remainingSize > 0) {
        this.stretchAllRatio = totalWidth / sumAll;
        this.stretchAllColumnsWidth = [];
        this.needVerifyLastColumnWidth = true;
      } else if (this.stretch === 'last' && totalWidth !== Infinity) {
        var _columnWidth = this._getColumnWidth(totalColumns - 1);
        var lastColumnWidth = remainingSize + _columnWidth;

        this.stretchLastWidth = lastColumnWidth >= 0 ? lastColumnWidth : _columnWidth;
      }
    }

    /**
     * Get stretched column width based on stretchH (all or last) setting passed in handsontable instance.
     *
     * @param {Number} column
     * @param {Number} baseWidth
     * @returns {Number|null}
     */

  }, {
    key: 'getStretchedColumnWidth',
    value: function getStretchedColumnWidth(column, baseWidth) {
      var result = null;

      if (this.stretch === 'all' && this.stretchAllRatio !== 0) {
        result = this._getStretchedAllColumnWidth(column, baseWidth);
      } else if (this.stretch === 'last' && this.stretchLastWidth !== 0) {
        result = this._getStretchedLastColumnWidth(column);
      }

      return result;
    }

    /**
     * @param {Number} column
     * @param {Number} baseWidth
     * @returns {Number}
     * @private
     */

  }, {
    key: '_getStretchedAllColumnWidth',
    value: function _getStretchedAllColumnWidth(column, baseWidth) {
      var sumRatioWidth = 0;
      var priv = privatePool.get(this);
      var totalColumns = priv.totalColumns;

      if (!this.stretchAllColumnsWidth[column]) {
        var stretchedWidth = Math.round(baseWidth * this.stretchAllRatio);
        var newStretchedWidth = priv.stretchingColumnWidthFn(stretchedWidth, column);

        if (newStretchedWidth === void 0) {
          this.stretchAllColumnsWidth[column] = stretchedWidth;
        } else {
          this.stretchAllColumnsWidth[column] = isNaN(newStretchedWidth) ? this._getColumnWidth(column) : newStretchedWidth;
        }
      }

      if (this.stretchAllColumnsWidth.length === totalColumns && this.needVerifyLastColumnWidth) {
        this.needVerifyLastColumnWidth = false;

        for (var i = 0; i < this.stretchAllColumnsWidth.length; i++) {
          sumRatioWidth += this.stretchAllColumnsWidth[i];
        }
        if (sumRatioWidth !== this.totalTargetWidth) {
          this.stretchAllColumnsWidth[this.stretchAllColumnsWidth.length - 1] += this.totalTargetWidth - sumRatioWidth;
        }
      }

      return this.stretchAllColumnsWidth[column];
    }

    /**
     * @param {Number} column
     * @returns {Number|null}
     * @private
     */

  }, {
    key: '_getStretchedLastColumnWidth',
    value: function _getStretchedLastColumnWidth(column) {
      var priv = privatePool.get(this);
      var totalColumns = priv.totalColumns;

      if (column === totalColumns - 1) {
        return this.stretchLastWidth;
      }

      return null;
    }

    /**
     * @param {Number} column Column index.
     * @returns {Number}
     * @private
     */

  }, {
    key: '_getColumnWidth',
    value: function _getColumnWidth(column) {
      var width = privatePool.get(this).columnWidthFn(column);

      if (width === void 0) {
        width = ViewportColumnsCalculator.DEFAULT_WIDTH;
      }

      return width;
    }
  }]);

  return ViewportColumnsCalculator;
}();

exports.default = ViewportColumnsCalculator;

/***/ }),
/* 252 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


exports.__esModule = true;

var _createClass = 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); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

var privatePool = new WeakMap();

/**
 * Calculates indexes of rows to render OR rows that are visible.
 * To redo the calculation, you need to create a new calculator.
 *
 * @class ViewportRowsCalculator
 */

var ViewportRowsCalculator = function () {
  _createClass(ViewportRowsCalculator, null, [{
    key: "DEFAULT_HEIGHT",

    /**
     * Default row height
     *
     * @type {Number}
     */
    get: function get() {
      return 23;
    }

    /**
     * @param {Number} viewportHeight Height of the viewport
     * @param {Number} scrollOffset Current vertical scroll position of the viewport
     * @param {Number} totalRows Total number of rows
     * @param {Function} rowHeightFn Function that returns the height of the row at a given index (in px)
     * @param {Function} overrideFn Function that changes calculated this.startRow, this.endRow (used by MergeCells plugin)
     * @param {Boolean} onlyFullyVisible if `true`, only startRow and endRow will be indexes of rows that are fully in viewport
     * @param {Number} horizontalScrollbarHeight
     */

  }]);

  function ViewportRowsCalculator(viewportHeight, scrollOffset, totalRows, rowHeightFn, overrideFn, onlyFullyVisible, horizontalScrollbarHeight) {
    _classCallCheck(this, ViewportRowsCalculator);

    privatePool.set(this, {
      viewportHeight: viewportHeight,
      scrollOffset: scrollOffset,
      totalRows: totalRows,
      rowHeightFn: rowHeightFn,
      overrideFn: overrideFn,
      onlyFullyVisible: onlyFullyVisible,
      horizontalScrollbarHeight: horizontalScrollbarHeight
    });

    /**
     * Number of rendered/visible rows
     *
     * @type {Number}
     */
    this.count = 0;

    /**
     * Index of the first rendered/visible row (can be overwritten using overrideFn)
     *
     * @type {Number|null}
     */
    this.startRow = null;

    /**
     * Index of the last rendered/visible row (can be overwritten using overrideFn)
     *
     * @type {null}
     */
    this.endRow = null;

    /**
     * Position of the first rendered/visible row (in px)
     *
     * @type {Number|null}
     */
    this.startPosition = null;

    this.calculate();
  }

  /**
   * Calculates viewport
   */


  _createClass(ViewportRowsCalculator, [{
    key: "calculate",
    value: function calculate() {
      var sum = 0;
      var needReverse = true;
      var startPositions = [];

      var priv = privatePool.get(this);
      var onlyFullyVisible = priv.onlyFullyVisible;
      var overrideFn = priv.overrideFn;
      var rowHeightFn = priv.rowHeightFn;
      var scrollOffset = priv.scrollOffset;
      var totalRows = priv.totalRows;
      var viewportHeight = priv.viewportHeight;
      var horizontalScrollbarHeight = priv.horizontalScrollbarHeight || 0;
      var rowHeight = void 0;

      // Calculate the number (start and end index) of rows needed
      for (var i = 0; i < totalRows; i++) {
        rowHeight = rowHeightFn(i);

        if (rowHeight === undefined) {
          rowHeight = ViewportRowsCalculator.DEFAULT_HEIGHT;
        }
        if (sum <= scrollOffset && !onlyFullyVisible) {
          this.startRow = i;
        }

        // the row is within the "visible range"
        if (sum >= scrollOffset && sum + rowHeight <= scrollOffset + viewportHeight - horizontalScrollbarHeight) {
          if (this.startRow === null) {
            this.startRow = i;
          }
          this.endRow = i;
        }
        startPositions.push(sum);
        sum += rowHeight;

        if (!onlyFullyVisible) {
          this.endRow = i;
        }
        if (sum >= scrollOffset + viewportHeight - horizontalScrollbarHeight) {
          needReverse = false;
          break;
        }
      }

      // If the estimation has reached the last row and there is still some space available in the viewport,
      // we need to render in reverse in order to fill the whole viewport with rows
      if (this.endRow === totalRows - 1 && needReverse) {
        this.startRow = this.endRow;

        while (this.startRow > 0) {
          // rowHeight is the height of the last row
          var viewportSum = startPositions[this.endRow] + rowHeight - startPositions[this.startRow - 1];

          if (viewportSum <= viewportHeight - horizontalScrollbarHeight || !onlyFullyVisible) {
            this.startRow--;
          }
          if (viewportSum >= viewportHeight - horizontalScrollbarHeight) {
            break;
          }
        }
      }

      if (this.startRow !== null && overrideFn) {
        overrideFn(this);
      }
      this.startPosition = startPositions[this.startRow];

      if (this.startPosition == void 0) {
        this.startPosition = null;
      }
      if (this.startRow !== null) {
        this.count = this.endRow - this.startRow + 1;
      }
    }
  }]);

  return ViewportRowsCalculator;
}();

exports.default = ViewportRowsCalculator;

/***/ }),
/* 253 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


exports.__esModule = true;

var _createClass = 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); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

var _element = __webpack_require__(0);

var _object = __webpack_require__(3);

var _string = __webpack_require__(28);

var _event = __webpack_require__(254);

var _event2 = _interopRequireDefault(_event);

var _overlays = __webpack_require__(257);

var _overlays2 = _interopRequireDefault(_overlays);

var _scroll = __webpack_require__(258);

var _scroll2 = _interopRequireDefault(_scroll);

var _settings = __webpack_require__(259);

var _settings2 = _interopRequireDefault(_settings);

var _table = __webpack_require__(260);

var _table2 = _interopRequireDefault(_table);

var _viewport = __webpack_require__(262);

var _viewport2 = _interopRequireDefault(_viewport);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

/**
 * @class Walkontable
 */
var Walkontable = function () {
  /**
   * @param {Object} settings
   */
  function Walkontable(settings) {
    _classCallCheck(this, Walkontable);

    var originalHeaders = [];

    // this is the namespace for global events
    this.guid = 'wt_' + (0, _string.randomString)();

    // bootstrap from settings
    if (settings.cloneSource) {
      this.cloneSource = settings.cloneSource;
      this.cloneOverlay = settings.cloneOverlay;
      this.wtSettings = settings.cloneSource.wtSettings;
      this.wtTable = new _table2.default(this, settings.table, settings.wtRootElement);
      this.wtScroll = new _scroll2.default(this);
      this.wtViewport = settings.cloneSource.wtViewport;
      this.wtEvent = new _event2.default(this);
      this.selections = this.cloneSource.selections;
    } else {
      this.wtSettings = new _settings2.default(this, settings);
      this.wtTable = new _table2.default(this, settings.table);
      this.wtScroll = new _scroll2.default(this);
      this.wtViewport = new _viewport2.default(this);
      this.wtEvent = new _event2.default(this);
      this.selections = this.getSetting('selections');
      this.wtOverlays = new _overlays2.default(this);
      this.exportSettingsAsClassNames();
    }

    // find original headers
    if (this.wtTable.THEAD.childNodes.length && this.wtTable.THEAD.childNodes[0].childNodes.length) {
      for (var c = 0, clen = this.wtTable.THEAD.childNodes[0].childNodes.length; c < clen; c++) {
        originalHeaders.push(this.wtTable.THEAD.childNodes[0].childNodes[c].innerHTML);
      }
      if (!this.getSetting('columnHeaders').length) {
        this.update('columnHeaders', [function (column, TH) {
          (0, _element.fastInnerText)(TH, originalHeaders[column]);
        }]);
      }
    }
    this.drawn = false;
    this.drawInterrupted = false;
  }

  /**
   * Force rerender of Walkontable
   *
   * @param {Boolean} [fastDraw=false] When `true`, try to refresh only the positions of borders without rerendering
   *                                   the data. It will only work if Table.draw() does not force
   *                                   rendering anyway
   * @returns {Walkontable}
   */


  _createClass(Walkontable, [{
    key: 'draw',
    value: function draw() {
      var fastDraw = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;

      this.drawInterrupted = false;

      if (!fastDraw && !(0, _element.isVisible)(this.wtTable.TABLE)) {
        // draw interrupted because TABLE is not visible
        this.drawInterrupted = true;
      } else {
        this.wtTable.draw(fastDraw);
      }

      return this;
    }

    /**
     * Returns the TD at coords. If topmost is set to true, returns TD from the topmost overlay layer,
     * if not set or set to false, returns TD from the master table.
     *
     * @param {CellCoords} coords
     * @param {Boolean} [topmost=false]
     * @returns {Object}
     */

  }, {
    key: 'getCell',
    value: function getCell(coords) {
      var topmost = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;

      if (!topmost) {
        return this.wtTable.getCell(coords);
      }

      var totalRows = this.wtSettings.getSetting('totalRows');
      var fixedRowsTop = this.wtSettings.getSetting('fixedRowsTop');
      var fixedRowsBottom = this.wtSettings.getSetting('fixedRowsBottom');
      var fixedColumns = this.wtSettings.getSetting('fixedColumnsLeft');

      if (coords.row < fixedRowsTop && coords.col < fixedColumns) {
        return this.wtOverlays.topLeftCornerOverlay.clone.wtTable.getCell(coords);
      } else if (coords.row < fixedRowsTop) {
        return this.wtOverlays.topOverlay.clone.wtTable.getCell(coords);
      } else if (coords.col < fixedColumns && coords.row >= totalRows - fixedRowsBottom) {
        if (this.wtOverlays.bottomLeftCornerOverlay && this.wtOverlays.bottomLeftCornerOverlay.clone) {
          return this.wtOverlays.bottomLeftCornerOverlay.clone.wtTable.getCell(coords);
        }
      } else if (coords.col < fixedColumns) {
        return this.wtOverlays.leftOverlay.clone.wtTable.getCell(coords);
      } else if (coords.row < totalRows && coords.row > totalRows - fixedRowsBottom) {
        if (this.wtOverlays.bottomOverlay && this.wtOverlays.bottomOverlay.clone) {
          return this.wtOverlays.bottomOverlay.clone.wtTable.getCell(coords);
        }
      }

      return this.wtTable.getCell(coords);
    }

    /**
     * @param {Object} settings
     * @param {*} value
     * @returns {Walkontable}
     */

  }, {
    key: 'update',
    value: function update(settings, value) {
      return this.wtSettings.update(settings, value);
    }

    /**
     * Scroll the viewport to a row at the given index in the data source
     *
     * @param {Number} row
     * @returns {Walkontable}
     */

  }, {
    key: 'scrollVertical',
    value: function scrollVertical(row) {
      this.wtOverlays.topOverlay.scrollTo(row);
      this.getSetting('onScrollVertically');

      return this;
    }

    /**
     * Scroll the viewport to a column at the given index in the data source
     *
     * @param {Number} column
     * @returns {Walkontable}
     */

  }, {
    key: 'scrollHorizontal',
    value: function scrollHorizontal(column) {
      this.wtOverlays.leftOverlay.scrollTo(column);
      this.getSetting('onScrollHorizontally');

      return this;
    }

    /**
     * Scrolls the viewport to a cell (rerenders if needed)
     *
     * @param {CellCoords} coords
     * @returns {Walkontable}
     */

  }, {
    key: 'scrollViewport',
    value: function scrollViewport(coords) {
      this.wtScroll.scrollViewport(coords);

      return this;
    }

    /**
     * @returns {Array}
     */

  }, {
    key: 'getViewport',
    value: function getViewport() {
      return [this.wtTable.getFirstVisibleRow(), this.wtTable.getFirstVisibleColumn(), this.wtTable.getLastVisibleRow(), this.wtTable.getLastVisibleColumn()];
    }

    /**
     * Get overlay name
     *
     * @returns {String}
     */

  }, {
    key: 'getOverlayName',
    value: function getOverlayName() {
      return this.cloneOverlay ? this.cloneOverlay.type : 'master';
    }

    /**
     * Check overlay type of this Walkontable instance.
     *
     * @param {String} name Clone type @see {Overlay.CLONE_TYPES}.
     * @returns {Boolean}
     */

  }, {
    key: 'isOverlayName',
    value: function isOverlayName(name) {
      if (this.cloneOverlay) {
        return this.cloneOverlay.type === name;
      }

      return false;
    }

    /**
     * Export settings as class names added to the parent element of the table.
     */

  }, {
    key: 'exportSettingsAsClassNames',
    value: function exportSettingsAsClassNames() {
      var _this = this;

      var toExport = {
        rowHeaders: ['array'],
        columnHeaders: ['array']
      };
      var allClassNames = [];
      var newClassNames = [];

      (0, _object.objectEach)(toExport, function (optionType, key) {
        if (optionType.indexOf('array') > -1 && _this.getSetting(key).length) {
          newClassNames.push('ht' + (0, _string.toUpperCaseFirst)(key));
        }
        allClassNames.push('ht' + (0, _string.toUpperCaseFirst)(key));
      });
      (0, _element.removeClass)(this.wtTable.wtRootElement.parentNode, allClassNames);
      (0, _element.addClass)(this.wtTable.wtRootElement.parentNode, newClassNames);
    }

    /**
     * Get/Set Walkontable instance setting
     *
     * @param {String} key
     * @param {*} [param1]
     * @param {*} [param2]
     * @param {*} [param3]
     * @param {*} [param4]
     * @returns {*}
     */

  }, {
    key: 'getSetting',
    value: function getSetting(key, param1, param2, param3, param4) {
      // this is faster than .apply - https://github.com/handsontable/handsontable/wiki/JavaScript-&-DOM-performance-tips
      return this.wtSettings.getSetting(key, param1, param2, param3, param4);
    }

    /**
     * Checks if setting exists
     *
     * @param {String} key
     * @returns {Boolean}
     */

  }, {
    key: 'hasSetting',
    value: function hasSetting(key) {
      return this.wtSettings.has(key);
    }

    /**
     * Destroy instance
     */

  }, {
    key: 'destroy',
    value: function destroy() {
      this.wtOverlays.destroy();
      this.wtEvent.destroy();
    }
  }]);

  return Walkontable;
}();

exports.default = Walkontable;

/***/ }),
/* 254 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


exports.__esModule = true;

var _element = __webpack_require__(0);

var _function = __webpack_require__(35);

var _browser = __webpack_require__(22);

var _eventManager = __webpack_require__(4);

var _eventManager2 = _interopRequireDefault(_eventManager);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

/**
 *
 */
function Event(instance) {
  var that = this;
  var eventManager = new _eventManager2.default(instance);

  this.instance = instance;

  var dblClickOrigin = [null, null];
  this.dblClickTimeout = [null, null];

  var onMouseDown = function onMouseDown(event) {
    var activeElement = document.activeElement;
    var getParentNode = (0, _function.partial)(_element.getParent, event.realTarget);
    var realTarget = event.realTarget;

    // ignore focusable element from mouse down processing (https://github.com/handsontable/handsontable/issues/3555)
    if (realTarget === activeElement || getParentNode(0) === activeElement || getParentNode(1) === activeElement) {
      return;
    }

    var cell = that.parentCell(realTarget);

    if ((0, _element.hasClass)(realTarget, 'corner')) {
      that.instance.getSetting('onCellCornerMouseDown', event, realTarget);
    } else if (cell.TD) {
      if (that.instance.hasSetting('onCellMouseDown')) {
        that.instance.getSetting('onCellMouseDown', event, cell.coords, cell.TD, that.instance);
      }
    }

    if (event.button !== 2) {
      // if not right mouse button
      if (cell.TD) {
        dblClickOrigin[0] = cell.TD;
        clearTimeout(that.dblClickTimeout[0]);
        that.dblClickTimeout[0] = setTimeout(function () {
          dblClickOrigin[0] = null;
        }, 1000);
      }
    }
  };

  var onTouchMove = function onTouchMove(event) {
    that.instance.touchMoving = true;
  };

  var longTouchTimeout;

  var onTouchStart = function onTouchStart(event) {
    var container = this;

    eventManager.addEventListener(this, 'touchmove', onTouchMove);

    // Prevent cell selection when scrolling with touch event - not the best solution performance-wise
    that.checkIfTouchMove = setTimeout(function () {
      if (that.instance.touchMoving === true) {
        that.instance.touchMoving = void 0;

        eventManager.removeEventListener('touchmove', onTouchMove, false);
      }

      onMouseDown(event);
    }, 30);
  };

  var onMouseOver = function onMouseOver(event) {
    var table, td, mainWOT;

    if (that.instance.hasSetting('onCellMouseOver')) {
      table = that.instance.wtTable.TABLE;
      td = (0, _element.closestDown)(event.realTarget, ['TD', 'TH'], table);
      mainWOT = that.instance.cloneSource || that.instance;

      if (td && td !== mainWOT.lastMouseOver && (0, _element.isChildOf)(td, table)) {
        mainWOT.lastMouseOver = td;

        that.instance.getSetting('onCellMouseOver', event, that.instance.wtTable.getCoords(td), td, that.instance);
      }
    }
  };

  var onMouseOut = function onMouseOut(event) {
    var table = void 0;
    var lastTD = void 0;
    var nextTD = void 0;

    if (that.instance.hasSetting('onCellMouseOut')) {
      table = that.instance.wtTable.TABLE;
      lastTD = (0, _element.closestDown)(event.realTarget, ['TD', 'TH'], table);
      nextTD = (0, _element.closestDown)(event.relatedTarget, ['TD', 'TH'], table);

      if (lastTD && lastTD !== nextTD && (0, _element.isChildOf)(lastTD, table)) {
        that.instance.getSetting('onCellMouseOut', event, that.instance.wtTable.getCoords(lastTD), lastTD, that.instance);
      }
    }
  };

  var onMouseUp = function onMouseUp(event) {
    if (event.button !== 2) {
      // if not right mouse button
      var cell = that.parentCell(event.realTarget);

      if (cell.TD === dblClickOrigin[0] && cell.TD === dblClickOrigin[1]) {
        if ((0, _element.hasClass)(event.realTarget, 'corner')) {
          that.instance.getSetting('onCellCornerDblClick', event, cell.coords, cell.TD, that.instance);
        } else {
          that.instance.getSetting('onCellDblClick', event, cell.coords, cell.TD, that.instance);
        }

        dblClickOrigin[0] = null;
        dblClickOrigin[1] = null;
      } else if (cell.TD === dblClickOrigin[0]) {
        that.instance.getSetting('onCellMouseUp', event, cell.coords, cell.TD, that.instance);

        dblClickOrigin[1] = cell.TD;
        clearTimeout(that.dblClickTimeout[1]);
        that.dblClickTimeout[1] = setTimeout(function () {
          dblClickOrigin[1] = null;
        }, 500);
      } else if (cell.TD && that.instance.hasSetting('onCellMouseUp')) {
        that.instance.getSetting('onCellMouseUp', event, cell.coords, cell.TD, that.instance);
      }
    }
  };

  var onTouchEnd = function onTouchEnd(event) {
    clearTimeout(longTouchTimeout);
    // that.instance.longTouch == void 0;

    event.preventDefault();
    onMouseUp(event);

    // eventManager.removeEventListener(that.instance.wtTable.holder, "mouseup", onMouseUp);
  };

  eventManager.addEventListener(this.instance.wtTable.holder, 'mousedown', onMouseDown);
  eventManager.addEventListener(this.instance.wtTable.TABLE, 'mouseover', onMouseOver);
  eventManager.addEventListener(this.instance.wtTable.TABLE, 'mouseout', onMouseOut);
  eventManager.addEventListener(this.instance.wtTable.holder, 'mouseup', onMouseUp);

  // check if full HOT instance, or detached WOT AND run on mobile device
  if (this.instance.wtTable.holder.parentNode.parentNode && (0, _browser.isMobileBrowser)() && !that.instance.wtTable.isWorkingOnClone()) {
    var classSelector = '.' + this.instance.wtTable.holder.parentNode.className.split(' ').join('.');

    eventManager.addEventListener(this.instance.wtTable.holder, 'touchstart', function (event) {
      that.instance.touchApplied = true;
      if ((0, _element.isChildOf)(event.target, classSelector)) {
        onTouchStart.call(event.target, event);
      }
    });
    eventManager.addEventListener(this.instance.wtTable.holder, 'touchend', function (event) {
      that.instance.touchApplied = false;
      if ((0, _element.isChildOf)(event.target, classSelector)) {
        onTouchEnd.call(event.target, event);
      }
    });

    if (!that.instance.momentumScrolling) {
      that.instance.momentumScrolling = {};
    }
    eventManager.addEventListener(this.instance.wtTable.holder, 'scroll', function (event) {
      clearTimeout(that.instance.momentumScrolling._timeout);

      if (!that.instance.momentumScrolling.ongoing) {
        that.instance.getSetting('onBeforeTouchScroll');
      }
      that.instance.momentumScrolling.ongoing = true;

      that.instance.momentumScrolling._timeout = setTimeout(function () {
        if (!that.instance.touchApplied) {
          that.instance.momentumScrolling.ongoing = false;

          that.instance.getSetting('onAfterMomentumScroll');
        }
      }, 200);
    });
  }

  eventManager.addEventListener(window, 'resize', function () {
    if (that.instance.getSetting('stretchH') !== 'none') {
      that.instance.draw();
    }
  });

  this.destroy = function () {
    clearTimeout(this.dblClickTimeout[0]);
    clearTimeout(this.dblClickTimeout[1]);

    eventManager.destroy();
  };
}

Event.prototype.parentCell = function (elem) {
  var cell = {};
  var TABLE = this.instance.wtTable.TABLE;
  var TD = (0, _element.closestDown)(elem, ['TD', 'TH'], TABLE);

  if (TD) {
    cell.coords = this.instance.wtTable.getCoords(TD);
    cell.TD = TD;
  } else if ((0, _element.hasClass)(elem, 'wtBorder') && (0, _element.hasClass)(elem, 'current')) {
    cell.coords = this.instance.selections.current.cellRange.highlight; // selections.current is current selected cell
    cell.TD = this.instance.wtTable.getCell(cell.coords);
  } else if ((0, _element.hasClass)(elem, 'wtBorder') && (0, _element.hasClass)(elem, 'area')) {
    if (this.instance.selections.area.cellRange) {
      cell.coords = this.instance.selections.area.cellRange.to; // selections.area is area selected cells
      cell.TD = this.instance.wtTable.getCell(cell.coords);
    }
  }

  return cell;
};

exports.default = Event;

/***/ }),
/* 255 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


exports.__esModule = true;

var _createClass = 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); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

/**
 * @class ColumnFilter
 */
var ColumnFilter = function () {
  /**
   * @param {Number} offset
   * @param {Number} total
   * @param {Number} countTH
   */
  function ColumnFilter(offset, total, countTH) {
    _classCallCheck(this, ColumnFilter);

    this.offset = offset;
    this.total = total;
    this.countTH = countTH;
  }

  /**
   * @param index
   * @returns {Number}
   */


  _createClass(ColumnFilter, [{
    key: "offsetted",
    value: function offsetted(index) {
      return index + this.offset;
    }

    /**
     * @param index
     * @returns {Number}
     */

  }, {
    key: "unOffsetted",
    value: function unOffsetted(index) {
      return index - this.offset;
    }

    /**
     * @param index
     * @returns {Number}
     */

  }, {
    key: "renderedToSource",
    value: function renderedToSource(index) {
      return this.offsetted(index);
    }

    /**
     * @param index
     * @returns {Number}
     */

  }, {
    key: "sourceToRendered",
    value: function sourceToRendered(index) {
      return this.unOffsetted(index);
    }

    /**
     * @param index
     * @returns {Number}
     */

  }, {
    key: "offsettedTH",
    value: function offsettedTH(index) {
      return index - this.countTH;
    }

    /**
     * @param index
     * @returns {Number}
     */

  }, {
    key: "unOffsettedTH",
    value: function unOffsettedTH(index) {
      return index + this.countTH;
    }

    /**
     * @param index
     * @returns {Number}
     */

  }, {
    key: "visibleRowHeadedColumnToSourceColumn",
    value: function visibleRowHeadedColumnToSourceColumn(index) {
      return this.renderedToSource(this.offsettedTH(index));
    }

    /**
     * @param index
     * @returns {Number}
     */

  }, {
    key: "sourceColumnToVisibleRowHeadedColumn",
    value: function sourceColumnToVisibleRowHeadedColumn(index) {
      return this.unOffsettedTH(this.sourceToRendered(index));
    }
  }]);

  return ColumnFilter;
}();

exports.default = ColumnFilter;

/***/ }),
/* 256 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


exports.__esModule = true;

var _createClass = 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); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

/**
 * @class RowFilter
 */
var RowFilter = function () {
  /**
   * @param {Number} offset
   * @param {Number} total
   * @param {Number} countTH
   */
  function RowFilter(offset, total, countTH) {
    _classCallCheck(this, RowFilter);

    this.offset = offset;
    this.total = total;
    this.countTH = countTH;
  }

  /**
   * @param index
   * @returns {Number}
   */


  _createClass(RowFilter, [{
    key: "offsetted",
    value: function offsetted(index) {
      return index + this.offset;
    }

    /**
     * @param index
     * @returns {Number}
     */

  }, {
    key: "unOffsetted",
    value: function unOffsetted(index) {
      return index - this.offset;
    }

    /**
     * @param index
     * @returns {Number}
     */

  }, {
    key: "renderedToSource",
    value: function renderedToSource(index) {
      return this.offsetted(index);
    }

    /**
     * @param index
     * @returns {Number}
     */

  }, {
    key: "sourceToRendered",
    value: function sourceToRendered(index) {
      return this.unOffsetted(index);
    }

    /**
     * @param index
     * @returns {Number}
     */

  }, {
    key: "offsettedTH",
    value: function offsettedTH(index) {
      return index - this.countTH;
    }

    /**
     * @param index
     * @returns {Number}
     */

  }, {
    key: "unOffsettedTH",
    value: function unOffsettedTH(index) {
      return index + this.countTH;
    }

    /**
     * @param index
     * @returns {Number}
     */

  }, {
    key: "visibleColHeadedRowToSourceRow",
    value: function visibleColHeadedRowToSourceRow(index) {
      return this.renderedToSource(this.offsettedTH(index));
    }

    /**
     * @param index
     * @returns {Number}
     */

  }, {
    key: "sourceRowToVisibleColHeadedRow",
    value: function sourceRowToVisibleColHeadedRow(index) {
      return this.unOffsettedTH(this.sourceToRendered(index));
    }
  }]);

  return RowFilter;
}();

exports.default = RowFilter;

/***/ }),
/* 257 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


exports.__esModule = true;

var _createClass = 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); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

var _element = __webpack_require__(0);

var _array = __webpack_require__(2);

var _unicode = __webpack_require__(15);

var _browser = __webpack_require__(22);

var _eventManager = __webpack_require__(4);

var _eventManager2 = _interopRequireDefault(_eventManager);

var _base = __webpack_require__(29);

var _base2 = _interopRequireDefault(_base);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

/**
 * @class Overlays
 */
var Overlays = function () {
  /**
   * @param {Walkontable} wotInstance
   */
  function Overlays(wotInstance) {
    _classCallCheck(this, Overlays);

    this.wot = wotInstance;

    // legacy support
    this.instance = this.wot;
    this.eventManager = new _eventManager2.default(this.wot);

    this.wot.update('scrollbarWidth', (0, _element.getScrollbarWidth)());
    this.wot.update('scrollbarHeight', (0, _element.getScrollbarWidth)());

    this.scrollableElement = (0, _element.getScrollableElement)(this.wot.wtTable.TABLE);

    this.prepareOverlays();

    this.destroyed = false;
    this.keyPressed = false;
    this.spreaderLastSize = {
      width: null,
      height: null
    };
    this.overlayScrollPositions = {
      master: {
        top: 0,
        left: 0
      },
      top: {
        top: null,
        left: 0
      },
      bottom: {
        top: null,
        left: 0
      },
      left: {
        top: 0,
        left: null
      }
    };

    this.pendingScrollCallbacks = {
      master: {
        top: 0,
        left: 0
      },
      top: {
        left: 0
      },
      bottom: {
        left: 0
      },
      left: {
        top: 0
      }
    };

    this.verticalScrolling = false;
    this.horizontalScrolling = false;
    this.delegatedScrollCallback = false;

    this.registeredListeners = [];

    this.registerListeners();
  }

  /**
   * Prepare overlays based on user settings.
   *
   * @returns {Boolean} Returns `true` if changes applied to overlay needs scroll synchronization.
   */


  _createClass(Overlays, [{
    key: 'prepareOverlays',
    value: function prepareOverlays() {
      var syncScroll = false;

      if (this.topOverlay) {
        syncScroll = this.topOverlay.updateStateOfRendering() || syncScroll;
      } else {
        this.topOverlay = _base2.default.createOverlay(_base2.default.CLONE_TOP, this.wot);
      }

      if (!_base2.default.hasOverlay(_base2.default.CLONE_BOTTOM)) {
        this.bottomOverlay = {
          needFullRender: false,
          updateStateOfRendering: function updateStateOfRendering() {
            return false;
          }
        };
      }
      if (!_base2.default.hasOverlay(_base2.default.CLONE_BOTTOM_LEFT_CORNER)) {
        this.bottomLeftCornerOverlay = {
          needFullRender: false,
          updateStateOfRendering: function updateStateOfRendering() {
            return false;
          }
        };
      }

      if (this.bottomOverlay) {
        syncScroll = this.bottomOverlay.updateStateOfRendering() || syncScroll;
      } else {
        this.bottomOverlay = _base2.default.createOverlay(_base2.default.CLONE_BOTTOM, this.wot);
      }

      if (this.leftOverlay) {
        syncScroll = this.leftOverlay.updateStateOfRendering() || syncScroll;
      } else {
        this.leftOverlay = _base2.default.createOverlay(_base2.default.CLONE_LEFT, this.wot);
      }

      if (this.topOverlay.needFullRender && this.leftOverlay.needFullRender) {
        if (this.topLeftCornerOverlay) {
          syncScroll = this.topLeftCornerOverlay.updateStateOfRendering() || syncScroll;
        } else {
          this.topLeftCornerOverlay = _base2.default.createOverlay(_base2.default.CLONE_TOP_LEFT_CORNER, this.wot);
        }
      }

      if (this.bottomOverlay.needFullRender && this.leftOverlay.needFullRender) {
        if (this.bottomLeftCornerOverlay) {
          syncScroll = this.bottomLeftCornerOverlay.updateStateOfRendering() || syncScroll;
        } else {
          this.bottomLeftCornerOverlay = _base2.default.createOverlay(_base2.default.CLONE_BOTTOM_LEFT_CORNER, this.wot);
        }
      }

      if (this.wot.getSetting('debug') && !this.debug) {
        this.debug = _base2.default.createOverlay(_base2.default.CLONE_DEBUG, this.wot);
      }

      return syncScroll;
    }

    /**
     * Refresh and redraw table
     */

  }, {
    key: 'refreshAll',
    value: function refreshAll() {
      if (!this.wot.drawn) {
        return;
      }
      if (!this.wot.wtTable.holder.parentNode) {
        // Walkontable was detached from DOM, but this handler was not removed
        this.destroy();

        return;
      }
      this.wot.draw(true);

      if (this.verticalScrolling) {
        this.leftOverlay.onScroll();
      }

      if (this.horizontalScrolling) {
        this.topOverlay.onScroll();
      }

      this.verticalScrolling = false;
      this.horizontalScrolling = false;
    }

    /**
     * Register all necessary event listeners.
     */

  }, {
    key: 'registerListeners',
    value: function registerListeners() {
      var _this = this;

      var topOverlayScrollable = this.topOverlay.mainTableScrollableElement;
      var leftOverlayScrollable = this.leftOverlay.mainTableScrollableElement;

      var listenersToRegister = [];
      listenersToRegister.push([document.documentElement, 'keydown', function (event) {
        return _this.onKeyDown(event);
      }]);
      listenersToRegister.push([document.documentElement, 'keyup', function () {
        return _this.onKeyUp();
      }]);
      listenersToRegister.push([document, 'visibilitychange', function () {
        return _this.onKeyUp();
      }]);
      listenersToRegister.push([topOverlayScrollable, 'scroll', function (event) {
        return _this.onTableScroll(event);
      }]);

      if (topOverlayScrollable !== leftOverlayScrollable) {
        listenersToRegister.push([leftOverlayScrollable, 'scroll', function (event) {
          return _this.onTableScroll(event);
        }]);
      }

      if (this.topOverlay.needFullRender) {
        listenersToRegister.push([this.topOverlay.clone.wtTable.holder, 'scroll', function (event) {
          return _this.onTableScroll(event);
        }]);
        listenersToRegister.push([this.topOverlay.clone.wtTable.holder, 'wheel', function (event) {
          return _this.onTableScroll(event);
        }]);
      }

      if (this.bottomOverlay.needFullRender) {
        listenersToRegister.push([this.bottomOverlay.clone.wtTable.holder, 'scroll', function (event) {
          return _this.onTableScroll(event);
        }]);
        listenersToRegister.push([this.bottomOverlay.clone.wtTable.holder, 'wheel', function (event) {
          return _this.onTableScroll(event);
        }]);
      }

      if (this.leftOverlay.needFullRender) {
        listenersToRegister.push([this.leftOverlay.clone.wtTable.holder, 'scroll', function (event) {
          return _this.onTableScroll(event);
        }]);
        listenersToRegister.push([this.leftOverlay.clone.wtTable.holder, 'wheel', function (event) {
          return _this.onTableScroll(event);
        }]);
      }

      if (this.topLeftCornerOverlay && this.topLeftCornerOverlay.needFullRender) {
        listenersToRegister.push([this.topLeftCornerOverlay.clone.wtTable.holder, 'wheel', function (event) {
          return _this.onTableScroll(event);
        }]);
      }

      if (this.bottomLeftCornerOverlay && this.bottomLeftCornerOverlay.needFullRender) {
        listenersToRegister.push([this.bottomLeftCornerOverlay.clone.wtTable.holder, 'wheel', function (event) {
          return _this.onTableScroll(event);
        }]);
      }

      if (this.topOverlay.trimmingContainer !== window && this.leftOverlay.trimmingContainer !== window) {
        // This is necessary?
        // eventManager.addEventListener(window, 'scroll', (event) => this.refreshAll(event));
        listenersToRegister.push([window, 'wheel', function (event) {
          var overlay = void 0;
          var deltaY = event.wheelDeltaY || event.deltaY;
          var deltaX = event.wheelDeltaX || event.deltaX;

          if (_this.topOverlay.clone.wtTable.holder.contains(event.realTarget)) {
            overlay = 'top';
          } else if (_this.bottomOverlay.clone && _this.bottomOverlay.clone.wtTable.holder.contains(event.realTarget)) {
            overlay = 'bottom';
          } else if (_this.leftOverlay.clone.wtTable.holder.contains(event.realTarget)) {
            overlay = 'left';
          } else if (_this.topLeftCornerOverlay && _this.topLeftCornerOverlay.clone && _this.topLeftCornerOverlay.clone.wtTable.holder.contains(event.realTarget)) {
            overlay = 'topLeft';
          } else if (_this.bottomLeftCornerOverlay && _this.bottomLeftCornerOverlay.clone && _this.bottomLeftCornerOverlay.clone.wtTable.holder.contains(event.realTarget)) {
            overlay = 'bottomLeft';
          }

          if (overlay == 'top' && deltaY !== 0 || overlay == 'left' && deltaX !== 0 || overlay == 'bottom' && deltaY !== 0 || (overlay === 'topLeft' || overlay === 'bottomLeft') && (deltaY !== 0 || deltaX !== 0)) {

            event.preventDefault();
          }
        }]);
      }

      while (listenersToRegister.length) {
        var listener = listenersToRegister.pop();
        this.eventManager.addEventListener(listener[0], listener[1], listener[2]);

        this.registeredListeners.push(listener);
      }
    }

    /**
     * Deregister all previously registered listeners.
     */

  }, {
    key: 'deregisterListeners',
    value: function deregisterListeners() {
      while (this.registeredListeners.length) {
        var listener = this.registeredListeners.pop();
        this.eventManager.removeEventListener(listener[0], listener[1], listener[2]);
      }
    }

    /**
     * Scroll listener
     *
     * @param {Event} event
     */

  }, {
    key: 'onTableScroll',
    value: function onTableScroll(event) {
      // if mobile browser, do not update scroll positions, as the overlays are hidden during the scroll
      if ((0, _browser.isMobileBrowser)()) {
        return;
      }
      var masterHorizontal = this.leftOverlay.mainTableScrollableElement;
      var masterVertical = this.topOverlay.mainTableScrollableElement;
      var target = event.target;

      // For key press, sync only master -> overlay position because while pressing Walkontable.render is triggered
      // by hot.refreshBorder
      if (this.keyPressed) {
        if (masterVertical !== window && target !== window && !event.target.contains(masterVertical) || masterHorizontal !== window && target !== window && !event.target.contains(masterHorizontal)) {
          return;
        }
      }

      if (event.type === 'scroll') {
        this.syncScrollPositions(event);
      } else {
        this.translateMouseWheelToScroll(event);
      }
    }

    /**
     * Key down listener
     */

  }, {
    key: 'onKeyDown',
    value: function onKeyDown(event) {
      this.keyPressed = (0, _unicode.isKey)(event.keyCode, 'ARROW_UP|ARROW_RIGHT|ARROW_DOWN|ARROW_LEFT');
    }

    /**
     * Key up listener
     */

  }, {
    key: 'onKeyUp',
    value: function onKeyUp() {
      this.keyPressed = false;
    }

    /**
     * Translate wheel event into scroll event and sync scroll overlays position
     *
     * @private
     * @param {Event} event
     * @returns {Boolean}
     */

  }, {
    key: 'translateMouseWheelToScroll',
    value: function translateMouseWheelToScroll(event) {
      var topOverlay = this.topOverlay.clone.wtTable.holder;
      var bottomOverlay = this.bottomOverlay.clone ? this.bottomOverlay.clone.wtTable.holder : null;
      var leftOverlay = this.leftOverlay.clone.wtTable.holder;
      var topLeftCornerOverlay = this.topLeftCornerOverlay && this.topLeftCornerOverlay.clone ? this.topLeftCornerOverlay.clone.wtTable.holder : null;
      var bottomLeftCornerOverlay = this.bottomLeftCornerOverlay && this.bottomLeftCornerOverlay.clone ? this.bottomLeftCornerOverlay.clone.wtTable.holder : null;
      var mouseWheelSpeedRatio = -0.2;
      var deltaY = event.wheelDeltaY || -1 * event.deltaY;
      var deltaX = event.wheelDeltaX || -1 * event.deltaX;
      var parentHolder = null;
      var eventMockup = { type: 'wheel' };
      var tempElem = event.target;
      var delta = null;

      // Fix for extremely slow header scrolling with a mousewheel on Firefox
      if (event.deltaMode === 1) {
        deltaY *= 120;
        deltaX *= 120;
      }

      while (tempElem != document && tempElem != null) {
        if (tempElem.className.indexOf('wtHolder') > -1) {
          parentHolder = tempElem;
          break;
        }
        tempElem = tempElem.parentNode;
      }
      eventMockup.target = parentHolder;

      if (parentHolder === topLeftCornerOverlay || parentHolder === bottomLeftCornerOverlay) {
        this.syncScrollPositions(eventMockup, mouseWheelSpeedRatio * deltaX, 'x');
        this.syncScrollPositions(eventMockup, mouseWheelSpeedRatio * deltaY, 'y');
      } else {
        if (parentHolder === topOverlay || parentHolder === bottomOverlay) {
          delta = deltaY;
        } else if (parentHolder === leftOverlay) {
          delta = deltaX;
        }

        this.syncScrollPositions(eventMockup, mouseWheelSpeedRatio * delta);
      }

      return false;
    }

    /**
     * Synchronize scroll position between master table and overlay table.
     *
     * @private
     * @param {Event|Object} event
     * @param {Number} [fakeScrollValue=null]
     * @param {String} [fakeScrollDirection=null] `x` or `y`.
     */

  }, {
    key: 'syncScrollPositions',
    value: function syncScrollPositions(event) {
      var fakeScrollValue = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
      var fakeScrollDirection = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null;

      if (this.destroyed) {
        return;
      }
      if (arguments.length === 0) {
        this.syncScrollWithMaster();

        return;
      }
      var masterHorizontal = this.leftOverlay.mainTableScrollableElement;
      var masterVertical = this.topOverlay.mainTableScrollableElement;
      var target = event.target;
      var tempScrollValue = 0;
      var scrollValueChanged = false;
      var topOverlay = void 0;
      var leftOverlay = void 0;
      var topLeftCornerOverlay = void 0;
      var bottomLeftCornerOverlay = void 0;
      var bottomOverlay = void 0;
      var delegatedScroll = false;
      var preventOverflow = this.wot.getSetting('preventOverflow');

      if (this.topOverlay.needFullRender) {
        topOverlay = this.topOverlay.clone.wtTable.holder;
      }

      if (this.bottomOverlay.needFullRender) {
        bottomOverlay = this.bottomOverlay.clone.wtTable.holder;
      }

      if (this.leftOverlay.needFullRender) {
        leftOverlay = this.leftOverlay.clone.wtTable.holder;
      }

      if (this.leftOverlay.needFullRender && this.topOverlay.needFullRender) {
        topLeftCornerOverlay = this.topLeftCornerOverlay.clone.wtTable.holder;
      }

      if (this.leftOverlay.needFullRender && this.bottomOverlay.needFullRender) {
        bottomLeftCornerOverlay = this.bottomLeftCornerOverlay.clone.wtTable.holder;
      }

      if (target === document) {
        target = window;
      }

      if (target === masterHorizontal || target === masterVertical) {
        if (preventOverflow) {
          tempScrollValue = (0, _element.getScrollLeft)(this.scrollableElement);
        } else {
          tempScrollValue = (0, _element.getScrollLeft)(target);
        }

        // if scrolling the master table - populate the scroll values to both top and left overlays
        this.horizontalScrolling = true;
        this.overlayScrollPositions.master.left = tempScrollValue;
        scrollValueChanged = true;

        if (this.pendingScrollCallbacks.master.left > 0) {
          this.pendingScrollCallbacks.master.left--;
        } else {
          if (topOverlay && topOverlay.scrollLeft !== tempScrollValue) {

            if (fakeScrollValue == null) {
              this.pendingScrollCallbacks.top.left++;
            }

            topOverlay.scrollLeft = tempScrollValue;
            delegatedScroll = masterHorizontal !== window;
          }

          if (bottomOverlay && bottomOverlay.scrollLeft !== tempScrollValue) {

            if (fakeScrollValue == null) {
              this.pendingScrollCallbacks.bottom.left++;
            }

            bottomOverlay.scrollLeft = tempScrollValue;
            delegatedScroll = masterHorizontal !== window;
          }
        }

        tempScrollValue = (0, _element.getScrollTop)(target);

        this.verticalScrolling = true;
        this.overlayScrollPositions.master.top = tempScrollValue;
        scrollValueChanged = true;

        if (this.pendingScrollCallbacks.master.top > 0) {
          this.pendingScrollCallbacks.master.top--;
        } else if (leftOverlay && leftOverlay.scrollTop !== tempScrollValue) {
          if (fakeScrollValue == null) {
            this.pendingScrollCallbacks.left.top++;
          }

          leftOverlay.scrollTop = tempScrollValue;
          delegatedScroll = masterVertical !== window;
        }
      } else if (target === bottomOverlay) {
        tempScrollValue = (0, _element.getScrollLeft)(target);

        // if scrolling the bottom overlay - populate the horizontal scroll to the master table
        this.horizontalScrolling = true;
        this.overlayScrollPositions.bottom.left = tempScrollValue;
        scrollValueChanged = true;

        if (this.pendingScrollCallbacks.bottom.left > 0) {
          this.pendingScrollCallbacks.bottom.left--;
        } else {
          if (fakeScrollValue == null) {
            this.pendingScrollCallbacks.master.left++;
          }

          masterHorizontal.scrollLeft = tempScrollValue;

          if (topOverlay && topOverlay.scrollLeft !== tempScrollValue) {
            if (fakeScrollValue == null) {
              this.pendingScrollCallbacks.top.left++;
            }

            topOverlay.scrollLeft = tempScrollValue;
            delegatedScroll = masterVertical !== window;
          }
        }

        // "fake" scroll value calculated from the mousewheel event
        if (fakeScrollValue !== null) {
          scrollValueChanged = true;
          masterVertical.scrollTop += fakeScrollValue;
        }
      } else if (target === topOverlay) {
        tempScrollValue = (0, _element.getScrollLeft)(target);

        // if scrolling the top overlay - populate the horizontal scroll to the master table
        this.horizontalScrolling = true;
        this.overlayScrollPositions.top.left = tempScrollValue;
        scrollValueChanged = true;

        if (this.pendingScrollCallbacks.top.left > 0) {
          this.pendingScrollCallbacks.top.left--;
        } else {

          if (fakeScrollValue == null) {
            this.pendingScrollCallbacks.master.left++;
          }

          masterHorizontal.scrollLeft = tempScrollValue;
        }

        // "fake" scroll value calculated from the mousewheel event
        if (fakeScrollValue !== null) {
          scrollValueChanged = true;
          masterVertical.scrollTop += fakeScrollValue;
        }

        if (bottomOverlay && bottomOverlay.scrollLeft !== tempScrollValue) {
          if (fakeScrollValue == null) {
            this.pendingScrollCallbacks.bottom.left++;
          }

          bottomOverlay.scrollLeft = tempScrollValue;
          delegatedScroll = masterVertical !== window;
        }
      } else if (target === leftOverlay) {
        tempScrollValue = (0, _element.getScrollTop)(target);

        // if scrolling the left overlay - populate the vertical scroll to the master table
        if (this.overlayScrollPositions.left.top !== tempScrollValue) {
          this.verticalScrolling = true;
          this.overlayScrollPositions.left.top = tempScrollValue;
          scrollValueChanged = true;

          if (this.pendingScrollCallbacks.left.top > 0) {
            this.pendingScrollCallbacks.left.top--;
          } else {
            if (fakeScrollValue == null) {
              this.pendingScrollCallbacks.master.top++;
            }

            masterVertical.scrollTop = tempScrollValue;
          }
        }

        // "fake" scroll value calculated from the mousewheel event
        if (fakeScrollValue !== null) {
          scrollValueChanged = true;
          masterVertical.scrollLeft += fakeScrollValue;
        }
      } else if (target === topLeftCornerOverlay || target === bottomLeftCornerOverlay) {
        if (fakeScrollValue !== null) {
          scrollValueChanged = true;

          if (fakeScrollDirection === 'x') {
            masterVertical.scrollLeft += fakeScrollValue;
          } else if (fakeScrollDirection === 'y') {
            masterVertical.scrollTop += fakeScrollValue;
          }
        }
      }

      if (!this.keyPressed && scrollValueChanged && event.type === 'scroll') {
        if (this.delegatedScrollCallback) {
          this.delegatedScrollCallback = false;
        } else {
          this.refreshAll();
        }

        if (delegatedScroll) {
          this.delegatedScrollCallback = true;
        }
      }
    }

    /**
     * Synchronize overlay scrollbars with the master scrollbar
     */

  }, {
    key: 'syncScrollWithMaster',
    value: function syncScrollWithMaster() {
      var master = this.topOverlay.mainTableScrollableElement;
      var scrollLeft = master.scrollLeft,
          scrollTop = master.scrollTop;


      if (this.topOverlay.needFullRender) {
        this.topOverlay.clone.wtTable.holder.scrollLeft = scrollLeft;
      }
      if (this.bottomOverlay.needFullRender) {
        this.bottomOverlay.clone.wtTable.holder.scrollLeft = scrollLeft;
      }
      if (this.leftOverlay.needFullRender) {
        this.leftOverlay.clone.wtTable.holder.scrollTop = scrollTop;
      }
    }

    /**
     * Update the main scrollable elements for all the overlays.
     */

  }, {
    key: 'updateMainScrollableElements',
    value: function updateMainScrollableElements() {
      this.deregisterListeners();

      this.leftOverlay.updateMainScrollableElement();
      this.topOverlay.updateMainScrollableElement();

      if (this.bottomOverlay.needFullRender) {
        this.bottomOverlay.updateMainScrollableElement();
      }

      this.scrollableElement = (0, _element.getScrollableElement)(this.wot.wtTable.TABLE);

      this.registerListeners();
    }

    /**
     *
     */

  }, {
    key: 'destroy',
    value: function destroy() {
      this.eventManager.destroy();
      this.topOverlay.destroy();

      if (this.bottomOverlay.clone) {
        this.bottomOverlay.destroy();
      }
      this.leftOverlay.destroy();

      if (this.topLeftCornerOverlay) {
        this.topLeftCornerOverlay.destroy();
      }

      if (this.bottomLeftCornerOverlay && this.bottomLeftCornerOverlay.clone) {
        this.bottomLeftCornerOverlay.destroy();
      }

      if (this.debug) {
        this.debug.destroy();
      }
      this.destroyed = true;
    }

    /**
     * @param {Boolean} [fastDraw=false]
     */

  }, {
    key: 'refresh',
    value: function refresh() {
      var fastDraw = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;

      if (this.topOverlay.areElementSizesAdjusted && this.leftOverlay.areElementSizesAdjusted) {
        var container = this.wot.wtTable.wtRootElement.parentNode || this.wot.wtTable.wtRootElement;
        var width = container.clientWidth;
        var height = container.clientHeight;

        if (width !== this.spreaderLastSize.width || height !== this.spreaderLastSize.height) {
          this.spreaderLastSize.width = width;
          this.spreaderLastSize.height = height;
          this.adjustElementsSize();
        }
      }

      if (this.bottomOverlay.clone) {
        this.bottomOverlay.refresh(fastDraw);
      }

      this.leftOverlay.refresh(fastDraw);
      this.topOverlay.refresh(fastDraw);

      if (this.topLeftCornerOverlay) {
        this.topLeftCornerOverlay.refresh(fastDraw);
      }

      if (this.bottomLeftCornerOverlay && this.bottomLeftCornerOverlay.clone) {
        this.bottomLeftCornerOverlay.refresh(fastDraw);
      }

      if (this.debug) {
        this.debug.refresh(fastDraw);
      }
    }

    /**
     * Adjust overlays elements size and master table size
     *
     * @param {Boolean} [force=false]
     */

  }, {
    key: 'adjustElementsSize',
    value: function adjustElementsSize() {
      var force = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;

      var totalColumns = this.wot.getSetting('totalColumns');
      var totalRows = this.wot.getSetting('totalRows');
      var headerRowSize = this.wot.wtViewport.getRowHeaderWidth();
      var headerColumnSize = this.wot.wtViewport.getColumnHeaderHeight();
      var hiderStyle = this.wot.wtTable.hider.style;

      hiderStyle.width = headerRowSize + this.leftOverlay.sumCellSizes(0, totalColumns) + 'px';
      hiderStyle.height = headerColumnSize + this.topOverlay.sumCellSizes(0, totalRows) + 1 + 'px';

      this.topOverlay.adjustElementsSize(force);
      this.leftOverlay.adjustElementsSize(force);

      if (this.bottomOverlay.clone) {
        this.bottomOverlay.adjustElementsSize(force);
      }
    }

    /**
     *
     */

  }, {
    key: 'applyToDOM',
    value: function applyToDOM() {
      if (!this.topOverlay.areElementSizesAdjusted || !this.leftOverlay.areElementSizesAdjusted) {
        this.adjustElementsSize();
      }
      this.topOverlay.applyToDOM();

      if (this.bottomOverlay.clone) {
        this.bottomOverlay.applyToDOM();
      }

      this.leftOverlay.applyToDOM();
    }

    /**
     * Get the parent overlay of the provided element.
     *
     * @param {HTMLElement} element
     * @returns {Object|null}
     */

  }, {
    key: 'getParentOverlay',
    value: function getParentOverlay(element) {
      if (!element) {
        return null;
      }

      var overlays = [this.topOverlay, this.leftOverlay, this.bottomOverlay, this.topLeftCornerOverlay, this.bottomLeftCornerOverlay];
      var result = null;

      (0, _array.arrayEach)(overlays, function (elem, i) {
        if (!elem) {
          return;
        }

        if (elem.clone && elem.clone.wtTable.TABLE.contains(element)) {
          result = elem.clone;
        }
      });

      return result;
    }
  }]);

  return Overlays;
}();

exports.default = Overlays;

/***/ }),
/* 258 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


exports.__esModule = true;

var _createClass = 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); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

var _element = __webpack_require__(0);

var _number = __webpack_require__(5);

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

/**
 * @class Scroll
 */
var Scroll = function () {
  /**
   * @param {Walkontable} wotInstance
   */
  function Scroll(wotInstance) {
    _classCallCheck(this, Scroll);

    this.wot = wotInstance;

    // legacy support
    this.instance = wotInstance;
  }

  /**
   * Scrolls viewport to a cell by minimum number of cells
   *
   * @param {CellCoords} coords
   */


  _createClass(Scroll, [{
    key: 'scrollViewport',
    value: function scrollViewport(coords) {
      if (!this.wot.drawn) {
        return;
      }

      var _getVariables2 = this._getVariables(),
          topOverlay = _getVariables2.topOverlay,
          leftOverlay = _getVariables2.leftOverlay,
          totalRows = _getVariables2.totalRows,
          totalColumns = _getVariables2.totalColumns,
          fixedRowsTop = _getVariables2.fixedRowsTop,
          fixedRowsBottom = _getVariables2.fixedRowsBottom,
          fixedColumnsLeft = _getVariables2.fixedColumnsLeft;

      if (coords.row < 0 || coords.row > Math.max(totalRows - 1, 0)) {
        throw new Error('row ' + coords.row + ' does not exist');
      }

      if (coords.col < 0 || coords.col > Math.max(totalColumns - 1, 0)) {
        throw new Error('column ' + coords.col + ' does not exist');
      }

      if (coords.row >= fixedRowsTop && coords.row < this.getFirstVisibleRow()) {
        topOverlay.scrollTo(coords.row);
      } else if (coords.row > this.getLastVisibleRow() && coords.row < totalRows - fixedRowsBottom) {
        topOverlay.scrollTo(coords.row, true);
      }

      if (coords.col >= fixedColumnsLeft && coords.col < this.getFirstVisibleColumn()) {
        leftOverlay.scrollTo(coords.col);
      } else if (coords.col > this.getLastVisibleColumn()) {
        leftOverlay.scrollTo(coords.col, true);
      }
    }

    /**
     * Get first visible row based on virtual dom and how table is visible in browser window viewport.
     *
     * @returns {Number}
     */

  }, {
    key: 'getFirstVisibleRow',
    value: function getFirstVisibleRow() {
      var _getVariables3 = this._getVariables(),
          topOverlay = _getVariables3.topOverlay,
          wtTable = _getVariables3.wtTable,
          wtViewport = _getVariables3.wtViewport,
          totalRows = _getVariables3.totalRows,
          fixedRowsTop = _getVariables3.fixedRowsTop;

      var firstVisibleRow = wtTable.getFirstVisibleRow();

      if (topOverlay.mainTableScrollableElement === window) {
        var rootElementOffset = (0, _element.offset)(wtTable.wtRootElement);
        var totalTableHeight = (0, _element.innerHeight)(wtTable.hider);
        var windowHeight = (0, _element.innerHeight)(window);
        var windowScrollTop = (0, _element.getScrollTop)(window);

        // Only calculate firstVisibleRow when table didn't filled (from up) whole viewport space
        if (rootElementOffset.top + totalTableHeight - windowHeight <= windowScrollTop) {
          var rowsHeight = wtViewport.getColumnHeaderHeight();

          rowsHeight += topOverlay.sumCellSizes(0, fixedRowsTop);

          (0, _number.rangeEachReverse)(totalRows, 1, function (row) {
            rowsHeight += topOverlay.sumCellSizes(row - 1, row);

            if (rootElementOffset.top + totalTableHeight - rowsHeight <= windowScrollTop) {
              // Return physical row + 1
              firstVisibleRow = row;

              return false;
            }
          });
        }
      }

      return firstVisibleRow;
    }

    /**
     * Get last visible row based on virtual dom and how table is visible in browser window viewport.
     *
     * @returns {Number}
     */

  }, {
    key: 'getLastVisibleRow',
    value: function getLastVisibleRow() {
      var _getVariables4 = this._getVariables(),
          topOverlay = _getVariables4.topOverlay,
          wtTable = _getVariables4.wtTable,
          wtViewport = _getVariables4.wtViewport,
          totalRows = _getVariables4.totalRows;

      var lastVisibleRow = wtTable.getLastVisibleRow();

      if (topOverlay.mainTableScrollableElement === window) {
        var rootElementOffset = (0, _element.offset)(wtTable.wtRootElement);
        var windowHeight = (0, _element.innerHeight)(window);
        var windowScrollTop = (0, _element.getScrollTop)(window);

        // Only calculate lastVisibleRow when table didn't filled (from bottom) whole viewport space
        if (rootElementOffset.top > windowScrollTop) {
          var rowsHeight = wtViewport.getColumnHeaderHeight();

          (0, _number.rangeEach)(1, totalRows, function (row) {
            rowsHeight += topOverlay.sumCellSizes(row - 1, row);

            if (rootElementOffset.top + rowsHeight - windowScrollTop >= windowHeight) {
              // Return physical row - 1 (-2 because rangeEach gives row index + 1 - sumCellSizes requirements)
              lastVisibleRow = row - 2;

              return false;
            }
          });
        }
      }

      return lastVisibleRow;
    }

    /**
     * Get first visible column based on virtual dom and how table is visible in browser window viewport.
     *
     * @returns {Number}
     */

  }, {
    key: 'getFirstVisibleColumn',
    value: function getFirstVisibleColumn() {
      var _getVariables5 = this._getVariables(),
          leftOverlay = _getVariables5.leftOverlay,
          wtTable = _getVariables5.wtTable,
          wtViewport = _getVariables5.wtViewport,
          totalColumns = _getVariables5.totalColumns,
          fixedColumnsLeft = _getVariables5.fixedColumnsLeft;

      var firstVisibleColumn = wtTable.getFirstVisibleColumn();

      if (leftOverlay.mainTableScrollableElement === window) {
        var rootElementOffset = (0, _element.offset)(wtTable.wtRootElement);
        var totalTableWidth = (0, _element.innerWidth)(wtTable.hider);
        var windowWidth = (0, _element.innerWidth)(window);
        var windowScrollLeft = (0, _element.getScrollLeft)(window);

        // Only calculate firstVisibleColumn when table didn't filled (from left) whole viewport space
        if (rootElementOffset.left + totalTableWidth - windowWidth <= windowScrollLeft) {
          var columnsWidth = wtViewport.getRowHeaderWidth();

          (0, _number.rangeEachReverse)(totalColumns, 1, function (column) {
            columnsWidth += leftOverlay.sumCellSizes(column - 1, column);

            if (rootElementOffset.left + totalTableWidth - columnsWidth <= windowScrollLeft) {
              // Return physical column + 1
              firstVisibleColumn = column;

              return false;
            }
          });
        }
      }

      return firstVisibleColumn;
    }

    /**
     * Get last visible column based on virtual dom and how table is visible in browser window viewport.
     *
     * @returns {Number}
     */

  }, {
    key: 'getLastVisibleColumn',
    value: function getLastVisibleColumn() {
      var _getVariables6 = this._getVariables(),
          leftOverlay = _getVariables6.leftOverlay,
          wtTable = _getVariables6.wtTable,
          wtViewport = _getVariables6.wtViewport,
          totalColumns = _getVariables6.totalColumns;

      var lastVisibleColumn = wtTable.getLastVisibleColumn();

      if (leftOverlay.mainTableScrollableElement === window) {
        var rootElementOffset = (0, _element.offset)(wtTable.wtRootElement);
        var windowWidth = (0, _element.innerWidth)(window);
        var windowScrollLeft = (0, _element.getScrollLeft)(window);

        // Only calculate lastVisibleColumn when table didn't filled (from right) whole viewport space
        if (rootElementOffset.left > windowScrollLeft) {
          var columnsWidth = wtViewport.getRowHeaderWidth();

          (0, _number.rangeEach)(1, totalColumns, function (column) {
            columnsWidth += leftOverlay.sumCellSizes(column - 1, column);

            if (rootElementOffset.left + columnsWidth - windowScrollLeft >= windowWidth) {
              // Return physical column - 1 (-2 because rangeEach gives column index + 1 - sumCellSizes requirements)
              lastVisibleColumn = column - 2;

              return false;
            }
          });
        }
      }

      return lastVisibleColumn;
    }

    /**
     * Returns collection of variables used to rows and columns visibility calculations.
     *
     * @returns {Object}
     * @private
     */

  }, {
    key: '_getVariables',
    value: function _getVariables() {
      var wot = this.wot;
      var topOverlay = wot.wtOverlays.topOverlay;
      var leftOverlay = wot.wtOverlays.leftOverlay;
      var wtTable = wot.wtTable;
      var wtViewport = wot.wtViewport;
      var totalRows = wot.getSetting('totalRows');
      var totalColumns = wot.getSetting('totalColumns');
      var fixedRowsTop = wot.getSetting('fixedRowsTop');
      var fixedRowsBottom = wot.getSetting('fixedRowsBottom');
      var fixedColumnsLeft = wot.getSetting('fixedColumnsLeft');

      return {
        topOverlay: topOverlay,
        leftOverlay: leftOverlay,
        wtTable: wtTable,
        wtViewport: wtViewport,
        totalRows: totalRows,
        totalColumns: totalColumns,
        fixedRowsTop: fixedRowsTop,
        fixedRowsBottom: fixedRowsBottom,
        fixedColumnsLeft: fixedColumnsLeft
      };
    }
  }]);

  return Scroll;
}();

exports.default = Scroll;

/***/ }),
/* 259 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


exports.__esModule = true;

var _createClass = 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); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

var _element = __webpack_require__(0);

var _object = __webpack_require__(3);

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

/**
 * @class Settings
 */
var Settings = function () {
  /**
   * @param {Walkontable} wotInstance
   * @param {Object} settings
   */
  function Settings(wotInstance, settings) {
    var _this = this;

    _classCallCheck(this, Settings);

    this.wot = wotInstance;

    // legacy support
    this.instance = wotInstance;

    // default settings. void 0 means it is required, null means it can be empty
    this.defaults = {
      table: void 0,
      debug: false, // shows WalkontableDebugOverlay

      // presentation mode
      externalRowCalculator: false,
      stretchH: 'none', // values: all, last, none
      currentRowClassName: null,
      currentColumnClassName: null,
      preventOverflow: function preventOverflow() {
        return false;
      },


      // data source
      data: void 0,
      freezeOverlays: false,
      fixedColumnsLeft: 0,
      fixedRowsTop: 0,
      fixedRowsBottom: 0,
      minSpareRows: 0,

      // this must be array of functions: [function (row, TH) {}]
      rowHeaders: function rowHeaders() {
        return [];
      },


      // this must be array of functions: [function (column, TH) {}]
      columnHeaders: function columnHeaders() {
        return [];
      },

      totalRows: void 0,
      totalColumns: void 0,
      cellRenderer: function cellRenderer(row, column, TD) {
        var cellData = _this.getSetting('data', row, column);

        (0, _element.fastInnerText)(TD, cellData === void 0 || cellData === null ? '' : cellData);
      },

      // columnWidth: 50,
      columnWidth: function columnWidth(col) {
        // return undefined means use default size for the rendered cell content
      },
      rowHeight: function rowHeight(row) {
        // return undefined means use default size for the rendered cell content
      },

      defaultRowHeight: 23,
      defaultColumnWidth: 50,
      selections: null,
      hideBorderOnMouseDownOver: false,
      viewportRowCalculatorOverride: null,
      viewportColumnCalculatorOverride: null,

      // callbacks
      onCellMouseDown: null,
      onCellMouseOver: null,
      onCellMouseOut: null,
      onCellMouseUp: null,

      //    onCellMouseOut: null,
      onCellDblClick: null,
      onCellCornerMouseDown: null,
      onCellCornerDblClick: null,
      beforeDraw: null,
      onDraw: null,
      onBeforeDrawBorders: null,
      onScrollVertically: null,
      onScrollHorizontally: null,
      onBeforeTouchScroll: null,
      onAfterMomentumScroll: null,
      onBeforeStretchingColumnWidth: function onBeforeStretchingColumnWidth(width) {
        return width;
      },
      onModifyRowHeaderWidth: null,

      // constants
      scrollbarWidth: 10,
      scrollbarHeight: 10,

      renderAllRows: false,
      groups: false,
      rowHeaderWidth: null,
      columnHeaderHeight: null,
      headerClassName: null
    };

    // reference to settings
    this.settings = {};

    for (var i in this.defaults) {
      if ((0, _object.hasOwnProperty)(this.defaults, i)) {
        if (settings[i] !== void 0) {
          this.settings[i] = settings[i];
        } else if (this.defaults[i] === void 0) {
          throw new Error('A required setting "' + i + '" was not provided');
        } else {
          this.settings[i] = this.defaults[i];
        }
      }
    }
  }

  /**
   * Update settings
   *
   * @param {Object} settings
   * @param {*} value
   * @returns {Walkontable}
   */


  _createClass(Settings, [{
    key: 'update',
    value: function update(settings, value) {
      if (value === void 0) {
        // settings is object
        for (var i in settings) {
          if ((0, _object.hasOwnProperty)(settings, i)) {
            this.settings[i] = settings[i];
          }
        }
      } else {
        // if value is defined then settings is the key
        this.settings[settings] = value;
      }
      return this.wot;
    }

    /**
     * Get setting by name
     *
     * @param {String} key
     * @param {*} param1
     * @param {*} param2
     * @param {*} param3
     * @param {*} param4
     * @returns {*}
     */

  }, {
    key: 'getSetting',
    value: function getSetting(key, param1, param2, param3, param4) {
      if (typeof this.settings[key] === 'function') {
        // this is faster than .apply - https://github.com/handsontable/handsontable/wiki/JavaScript-&-DOM-performance-tips
        return this.settings[key](param1, param2, param3, param4);
      } else if (param1 !== void 0 && Array.isArray(this.settings[key])) {
        // perhaps this can be removed, it is only used in tests
        return this.settings[key][param1];
      }

      return this.settings[key];
    }

    /**
     * Checks if setting exists
     *
     * @param {Boolean} key
     * @returns {Boolean}
     */

  }, {
    key: 'has',
    value: function has(key) {
      return !!this.settings[key];
    }
  }]);

  return Settings;
}();

exports.default = Settings;

/***/ }),
/* 260 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


exports.__esModule = true;

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

var _createClass = 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); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

var _element = __webpack_require__(0);

var _function = __webpack_require__(35);

var _coords = __webpack_require__(43);

var _coords2 = _interopRequireDefault(_coords);

var _range = __webpack_require__(71);

var _range2 = _interopRequireDefault(_range);

var _column = __webpack_require__(255);

var _column2 = _interopRequireDefault(_column);

var _row = __webpack_require__(256);

var _row2 = _interopRequireDefault(_row);

var _tableRenderer = __webpack_require__(261);

var _tableRenderer2 = _interopRequireDefault(_tableRenderer);

var _base = __webpack_require__(29);

var _base2 = _interopRequireDefault(_base);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

/**
 *
 */
var Table = function () {
  /**
   * @param {Walkontable} wotInstance
   * @param {HTMLTableElement} table
   */
  function Table(wotInstance, table) {
    var _this = this;

    _classCallCheck(this, Table);

    this.wot = wotInstance;

    // legacy support
    this.instance = this.wot;
    this.TABLE = table;
    this.TBODY = null;
    this.THEAD = null;
    this.COLGROUP = null;
    this.tableOffset = 0;
    this.holderOffset = 0;

    (0, _element.removeTextNodes)(this.TABLE);

    this.spreader = this.createSpreader(this.TABLE);
    this.hider = this.createHider(this.spreader);
    this.holder = this.createHolder(this.hider);

    this.wtRootElement = this.holder.parentNode;
    this.alignOverlaysWithTrimmingContainer();
    this.fixTableDomTree();

    this.colgroupChildrenLength = this.COLGROUP.childNodes.length;
    this.theadChildrenLength = this.THEAD.firstChild ? this.THEAD.firstChild.childNodes.length : 0;
    this.tbodyChildrenLength = this.TBODY.childNodes.length;

    this.rowFilter = null;
    this.columnFilter = null;
    this.correctHeaderWidth = false;

    var origRowHeaderWidth = this.wot.wtSettings.settings.rowHeaderWidth;

    // Fix for jumping row headers (https://github.com/handsontable/handsontable/issues/3850)
    this.wot.wtSettings.settings.rowHeaderWidth = function () {
      return _this._modifyRowHeaderWidth(origRowHeaderWidth);
    };
  }

  /**
   *
   */


  _createClass(Table, [{
    key: 'fixTableDomTree',
    value: function fixTableDomTree() {
      this.TBODY = this.TABLE.querySelector('tbody');

      if (!this.TBODY) {
        this.TBODY = document.createElement('tbody');
        this.TABLE.appendChild(this.TBODY);
      }
      this.THEAD = this.TABLE.querySelector('thead');

      if (!this.THEAD) {
        this.THEAD = document.createElement('thead');
        this.TABLE.insertBefore(this.THEAD, this.TBODY);
      }
      this.COLGROUP = this.TABLE.querySelector('colgroup');

      if (!this.COLGROUP) {
        this.COLGROUP = document.createElement('colgroup');
        this.TABLE.insertBefore(this.COLGROUP, this.THEAD);
      }

      if (this.wot.getSetting('columnHeaders').length && !this.THEAD.childNodes.length) {
        this.THEAD.appendChild(document.createElement('TR'));
      }
    }

    /**
     * @param table
     * @returns {HTMLElement}
     */

  }, {
    key: 'createSpreader',
    value: function createSpreader(table) {
      var parent = table.parentNode;
      var spreader = void 0;

      if (!parent || parent.nodeType !== 1 || !(0, _element.hasClass)(parent, 'wtHolder')) {
        spreader = document.createElement('div');
        spreader.className = 'wtSpreader';

        if (parent) {
          // if TABLE is detached (e.g. in Jasmine test), it has no parentNode so we cannot attach holder to it
          parent.insertBefore(spreader, table);
        }
        spreader.appendChild(table);
      }
      spreader.style.position = 'relative';

      return spreader;
    }

    /**
     * @param spreader
     * @returns {HTMLElement}
     */

  }, {
    key: 'createHider',
    value: function createHider(spreader) {
      var parent = spreader.parentNode;
      var hider = void 0;

      if (!parent || parent.nodeType !== 1 || !(0, _element.hasClass)(parent, 'wtHolder')) {
        hider = document.createElement('div');
        hider.className = 'wtHider';

        if (parent) {
          // if TABLE is detached (e.g. in Jasmine test), it has no parentNode so we cannot attach holder to it
          parent.insertBefore(hider, spreader);
        }
        hider.appendChild(spreader);
      }

      return hider;
    }

    /**
     *
     * @param hider
     * @returns {HTMLElement}
     */

  }, {
    key: 'createHolder',
    value: function createHolder(hider) {
      var parent = hider.parentNode;
      var holder = void 0;

      if (!parent || parent.nodeType !== 1 || !(0, _element.hasClass)(parent, 'wtHolder')) {
        holder = document.createElement('div');
        holder.style.position = 'relative';
        holder.className = 'wtHolder';

        if (parent) {
          // if TABLE is detached (e.g. in Jasmine test), it has no parentNode so we cannot attach holder to it
          parent.insertBefore(holder, hider);
        }
        if (!this.isWorkingOnClone()) {
          holder.parentNode.className += 'ht_master handsontable';
        }
        holder.appendChild(hider);
      }

      return holder;
    }
  }, {
    key: 'alignOverlaysWithTrimmingContainer',
    value: function alignOverlaysWithTrimmingContainer() {
      var trimmingElement = (0, _element.getTrimmingContainer)(this.wtRootElement);

      if (!this.isWorkingOnClone()) {
        this.holder.parentNode.style.position = 'relative';

        if (trimmingElement === window) {
          var preventOverflow = this.wot.getSetting('preventOverflow');

          if (!preventOverflow) {
            this.holder.style.overflow = 'visible';
            this.wtRootElement.style.overflow = 'visible';
          }
        } else {
          this.holder.style.width = (0, _element.getStyle)(trimmingElement, 'width');
          this.holder.style.height = (0, _element.getStyle)(trimmingElement, 'height');
          this.holder.style.overflow = '';
        }
      }
    }
  }, {
    key: 'isWorkingOnClone',
    value: function isWorkingOnClone() {
      return !!this.wot.cloneSource;
    }

    /**
     * Redraws the table
     *
     * @param {Boolean} fastDraw If TRUE, will try to avoid full redraw and only update the border positions. If FALSE or UNDEFINED, will perform a full redraw
     * @returns {Table}
     */

  }, {
    key: 'draw',
    value: function draw(fastDraw) {
      var _wot = this.wot,
          wtOverlays = _wot.wtOverlays,
          wtViewport = _wot.wtViewport;

      var totalRows = this.instance.getSetting('totalRows');
      var rowHeaders = this.wot.getSetting('rowHeaders').length;
      var columnHeaders = this.wot.getSetting('columnHeaders').length;
      var syncScroll = false;

      if (!this.isWorkingOnClone()) {
        this.holderOffset = (0, _element.offset)(this.holder);
        fastDraw = wtViewport.createRenderCalculators(fastDraw);

        if (rowHeaders && !this.wot.getSetting('fixedColumnsLeft')) {
          var leftScrollPos = wtOverlays.leftOverlay.getScrollPosition();
          var previousState = this.correctHeaderWidth;

          this.correctHeaderWidth = leftScrollPos > 0;

          if (previousState !== this.correctHeaderWidth) {
            fastDraw = false;
          }
        }
      }

      if (!this.isWorkingOnClone()) {
        syncScroll = wtOverlays.prepareOverlays();
      }

      if (fastDraw) {
        if (!this.isWorkingOnClone()) {
          // in case we only scrolled without redraw, update visible rows information in oldRowsCalculator
          wtViewport.createVisibleCalculators();
        }
        if (wtOverlays) {
          wtOverlays.refresh(true);
        }
      } else {
        if (this.isWorkingOnClone()) {
          this.tableOffset = this.wot.cloneSource.wtTable.tableOffset;
        } else {
          this.tableOffset = (0, _element.offset)(this.TABLE);
        }
        var startRow = void 0;

        if (_base2.default.isOverlayTypeOf(this.wot.cloneOverlay, _base2.default.CLONE_DEBUG) || _base2.default.isOverlayTypeOf(this.wot.cloneOverlay, _base2.default.CLONE_TOP) || _base2.default.isOverlayTypeOf(this.wot.cloneOverlay, _base2.default.CLONE_TOP_LEFT_CORNER)) {
          startRow = 0;
        } else if (_base2.default.isOverlayTypeOf(this.instance.cloneOverlay, _base2.default.CLONE_BOTTOM) || _base2.default.isOverlayTypeOf(this.instance.cloneOverlay, _base2.default.CLONE_BOTTOM_LEFT_CORNER)) {
          startRow = Math.max(totalRows - this.wot.getSetting('fixedRowsBottom'), 0);
        } else {
          startRow = wtViewport.rowsRenderCalculator.startRow;
        }
        var startColumn = void 0;

        if (_base2.default.isOverlayTypeOf(this.wot.cloneOverlay, _base2.default.CLONE_DEBUG) || _base2.default.isOverlayTypeOf(this.wot.cloneOverlay, _base2.default.CLONE_LEFT) || _base2.default.isOverlayTypeOf(this.wot.cloneOverlay, _base2.default.CLONE_TOP_LEFT_CORNER) || _base2.default.isOverlayTypeOf(this.wot.cloneOverlay, _base2.default.CLONE_BOTTOM_LEFT_CORNER)) {
          startColumn = 0;
        } else {
          startColumn = wtViewport.columnsRenderCalculator.startColumn;
        }
        this.rowFilter = new _row2.default(startRow, totalRows, columnHeaders);
        this.columnFilter = new _column2.default(startColumn, this.wot.getSetting('totalColumns'), rowHeaders);

        this.alignOverlaysWithTrimmingContainer();
        this._doDraw(); // creates calculator after draw
      }
      this.refreshSelections(fastDraw);

      if (!this.isWorkingOnClone()) {
        wtOverlays.topOverlay.resetFixedPosition();

        if (wtOverlays.bottomOverlay.clone) {
          wtOverlays.bottomOverlay.resetFixedPosition();
        }

        wtOverlays.leftOverlay.resetFixedPosition();

        if (wtOverlays.topLeftCornerOverlay) {
          wtOverlays.topLeftCornerOverlay.resetFixedPosition();
        }

        if (wtOverlays.bottomLeftCornerOverlay && wtOverlays.bottomLeftCornerOverlay.clone) {
          wtOverlays.bottomLeftCornerOverlay.resetFixedPosition();
        }
      }
      if (syncScroll) {
        wtOverlays.syncScrollWithMaster();
      }
      this.wot.drawn = true;

      return this;
    }
  }, {
    key: '_doDraw',
    value: function _doDraw() {
      var wtRenderer = new _tableRenderer2.default(this);

      wtRenderer.render();
    }
  }, {
    key: 'removeClassFromCells',
    value: function removeClassFromCells(className) {
      var nodes = this.TABLE.querySelectorAll('.' + className);

      for (var i = 0, len = nodes.length; i < len; i++) {
        (0, _element.removeClass)(nodes[i], className);
      }
    }
  }, {
    key: 'refreshSelections',
    value: function refreshSelections(fastDraw) {
      if (!this.wot.selections) {
        return;
      }
      var len = this.wot.selections.length;

      if (fastDraw) {
        for (var i = 0; i < len; i++) {
          // there was no rerender, so we need to remove classNames by ourselves
          if (this.wot.selections[i].settings.className) {
            this.removeClassFromCells(this.wot.selections[i].settings.className);
          }
          if (this.wot.selections[i].settings.highlightHeaderClassName) {
            this.removeClassFromCells(this.wot.selections[i].settings.highlightHeaderClassName);
          }
          if (this.wot.selections[i].settings.highlightRowClassName) {
            this.removeClassFromCells(this.wot.selections[i].settings.highlightRowClassName);
          }
          if (this.wot.selections[i].settings.highlightColumnClassName) {
            this.removeClassFromCells(this.wot.selections[i].settings.highlightColumnClassName);
          }
        }
      }
      for (var _i = 0; _i < len; _i++) {
        this.wot.selections[_i].draw(this.wot, fastDraw);
      }
    }

    /**
     * Get cell element at coords.
     *
     * @param {CellCoords} coords
     * @returns {HTMLElement|Number} HTMLElement on success or Number one of the exit codes on error:
     *  -1 row before viewport
     *  -2 row after viewport
     */

  }, {
    key: 'getCell',
    value: function getCell(coords) {
      if (this.isRowBeforeRenderedRows(coords.row)) {
        // row before rendered rows
        return -1;
      } else if (this.isRowAfterRenderedRows(coords.row)) {
        // row after rendered rows
        return -2;
      }

      var TR = this.TBODY.childNodes[this.rowFilter.sourceToRendered(coords.row)];

      if (TR) {
        return TR.childNodes[this.columnFilter.sourceColumnToVisibleRowHeadedColumn(coords.col)];
      }
    }

    /**
     * getColumnHeader
     *
     * @param {Number} col Column index
     * @param {Number} [level=0] Header level (0 = most distant to the table)
     * @returns {Object} HTMLElement on success or undefined on error
     */

  }, {
    key: 'getColumnHeader',
    value: function getColumnHeader(col) {
      var level = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;

      var TR = this.THEAD.childNodes[level];

      if (TR) {
        return TR.childNodes[this.columnFilter.sourceColumnToVisibleRowHeadedColumn(col)];
      }
    }

    /**
     * getRowHeader
     *
     * @param {Number} row Row index
     * @returns {HTMLElement} HTMLElement on success or Number one of the exit codes on error: `null table doesn't have row headers`
     */

  }, {
    key: 'getRowHeader',
    value: function getRowHeader(row) {
      if (this.columnFilter.sourceColumnToVisibleRowHeadedColumn(0) === 0) {
        return null;
      }
      var TR = this.TBODY.childNodes[this.rowFilter.sourceToRendered(row)];

      if (TR) {
        return TR.childNodes[0];
      }
    }

    /**
     * Returns cell coords object for a given TD (or a child element of a TD element).
     *
     * @param {HTMLTableCellElement} TD A cell DOM element (or a child of one).
     * @returns {CellCoords|null} The coordinates of the provided TD element (or the closest TD element) or null, if the provided element is not applicable.
     */

  }, {
    key: 'getCoords',
    value: function getCoords(TD) {
      if (TD.nodeName !== 'TD' && TD.nodeName !== 'TH') {
        TD = (0, _element.closest)(TD, ['TD', 'TH']);
      }

      if (TD === null) {
        return null;
      }

      var TR = TD.parentNode;
      var CONTAINER = TR.parentNode;
      var row = (0, _element.index)(TR);
      var col = TD.cellIndex;

      if ((0, _element.overlayContainsElement)(_base2.default.CLONE_TOP_LEFT_CORNER, TD) || (0, _element.overlayContainsElement)(_base2.default.CLONE_TOP, TD)) {
        if (CONTAINER.nodeName === 'THEAD') {
          row -= CONTAINER.childNodes.length;
        }
      } else if (CONTAINER === this.THEAD) {
        row = this.rowFilter.visibleColHeadedRowToSourceRow(row);
      } else {
        row = this.rowFilter.renderedToSource(row);
      }

      if ((0, _element.overlayContainsElement)(_base2.default.CLONE_TOP_LEFT_CORNER, TD) || (0, _element.overlayContainsElement)(_base2.default.CLONE_LEFT, TD)) {
        col = this.columnFilter.offsettedTH(col);
      } else {
        col = this.columnFilter.visibleRowHeadedColumnToSourceColumn(col);
      }

      return new _coords2.default(row, col);
    }
  }, {
    key: 'getTrForRow',
    value: function getTrForRow(row) {
      return this.TBODY.childNodes[this.rowFilter.sourceToRendered(row)];
    }
  }, {
    key: 'getFirstRenderedRow',
    value: function getFirstRenderedRow() {
      return this.wot.wtViewport.rowsRenderCalculator.startRow;
    }
  }, {
    key: 'getFirstVisibleRow',
    value: function getFirstVisibleRow() {
      return this.wot.wtViewport.rowsVisibleCalculator.startRow;
    }
  }, {
    key: 'getFirstRenderedColumn',
    value: function getFirstRenderedColumn() {
      return this.wot.wtViewport.columnsRenderCalculator.startColumn;
    }

    /**
     * @returns {Number} Returns -1 if no row is visible
     */

  }, {
    key: 'getFirstVisibleColumn',
    value: function getFirstVisibleColumn() {
      return this.wot.wtViewport.columnsVisibleCalculator.startColumn;
    }

    /**
     * @returns {Number} Returns -1 if no row is visible
     */

  }, {
    key: 'getLastRenderedRow',
    value: function getLastRenderedRow() {
      return this.wot.wtViewport.rowsRenderCalculator.endRow;
    }
  }, {
    key: 'getLastVisibleRow',
    value: function getLastVisibleRow() {
      return this.wot.wtViewport.rowsVisibleCalculator.endRow;
    }
  }, {
    key: 'getLastRenderedColumn',
    value: function getLastRenderedColumn() {
      return this.wot.wtViewport.columnsRenderCalculator.endColumn;
    }

    /**
     * @returns {Number} Returns -1 if no column is visible
     */

  }, {
    key: 'getLastVisibleColumn',
    value: function getLastVisibleColumn() {
      return this.wot.wtViewport.columnsVisibleCalculator.endColumn;
    }
  }, {
    key: 'isRowBeforeRenderedRows',
    value: function isRowBeforeRenderedRows(row) {
      return this.rowFilter && this.rowFilter.sourceToRendered(row) < 0 && row >= 0;
    }
  }, {
    key: 'isRowAfterViewport',
    value: function isRowAfterViewport(row) {
      return this.rowFilter && this.rowFilter.sourceToRendered(row) > this.getLastVisibleRow();
    }
  }, {
    key: 'isRowAfterRenderedRows',
    value: function isRowAfterRenderedRows(row) {
      return this.rowFilter && this.rowFilter.sourceToRendered(row) > this.getLastRenderedRow();
    }
  }, {
    key: 'isColumnBeforeViewport',
    value: function isColumnBeforeViewport(column) {
      return this.columnFilter && this.columnFilter.sourceToRendered(column) < 0 && column >= 0;
    }
  }, {
    key: 'isColumnAfterViewport',
    value: function isColumnAfterViewport(column) {
      return this.columnFilter && this.columnFilter.sourceToRendered(column) > this.getLastVisibleColumn();
    }
  }, {
    key: 'isLastRowFullyVisible',
    value: function isLastRowFullyVisible() {
      return this.getLastVisibleRow() === this.getLastRenderedRow();
    }
  }, {
    key: 'isLastColumnFullyVisible',
    value: function isLastColumnFullyVisible() {
      return this.getLastVisibleColumn() === this.getLastRenderedColumn();
    }
  }, {
    key: 'getRenderedColumnsCount',
    value: function getRenderedColumnsCount() {
      var columnsCount = this.wot.wtViewport.columnsRenderCalculator.count;
      var totalColumns = this.wot.getSetting('totalColumns');

      if (this.wot.isOverlayName(_base2.default.CLONE_DEBUG)) {
        columnsCount = totalColumns;
      } else if (this.wot.isOverlayName(_base2.default.CLONE_LEFT) || this.wot.isOverlayName(_base2.default.CLONE_TOP_LEFT_CORNER) || this.wot.isOverlayName(_base2.default.CLONE_BOTTOM_LEFT_CORNER)) {
        return Math.min(this.wot.getSetting('fixedColumnsLeft'), totalColumns);
      }

      return columnsCount;
    }
  }, {
    key: 'getRenderedRowsCount',
    value: function getRenderedRowsCount() {
      var rowsCount = this.wot.wtViewport.rowsRenderCalculator.count;
      var totalRows = this.wot.getSetting('totalRows');

      if (this.wot.isOverlayName(_base2.default.CLONE_DEBUG)) {
        rowsCount = totalRows;
      } else if (this.wot.isOverlayName(_base2.default.CLONE_TOP) || this.wot.isOverlayName(_base2.default.CLONE_TOP_LEFT_CORNER)) {
        rowsCount = Math.min(this.wot.getSetting('fixedRowsTop'), totalRows);
      } else if (this.wot.isOverlayName(_base2.default.CLONE_BOTTOM) || this.wot.isOverlayName(_base2.default.CLONE_BOTTOM_LEFT_CORNER)) {
        rowsCount = Math.min(this.wot.getSetting('fixedRowsBottom'), totalRows);
      }

      return rowsCount;
    }
  }, {
    key: 'getVisibleRowsCount',
    value: function getVisibleRowsCount() {
      return this.wot.wtViewport.rowsVisibleCalculator.count;
    }
  }, {
    key: 'allRowsInViewport',
    value: function allRowsInViewport() {
      return this.wot.getSetting('totalRows') == this.getVisibleRowsCount();
    }

    /**
     * Checks if any of the row's cells content exceeds its initial height, and if so, returns the oversized height
     *
     * @param {Number} sourceRow
     * @returns {Number}
     */

  }, {
    key: 'getRowHeight',
    value: function getRowHeight(sourceRow) {
      var height = this.wot.wtSettings.settings.rowHeight(sourceRow);
      var oversizedHeight = this.wot.wtViewport.oversizedRows[sourceRow];

      if (oversizedHeight !== void 0) {
        height = height === void 0 ? oversizedHeight : Math.max(height, oversizedHeight);
      }

      return height;
    }
  }, {
    key: 'getColumnHeaderHeight',
    value: function getColumnHeaderHeight(level) {
      var height = this.wot.wtSettings.settings.defaultRowHeight;
      var oversizedHeight = this.wot.wtViewport.oversizedColumnHeaders[level];

      if (oversizedHeight !== void 0) {
        height = height ? Math.max(height, oversizedHeight) : oversizedHeight;
      }

      return height;
    }
  }, {
    key: 'getVisibleColumnsCount',
    value: function getVisibleColumnsCount() {
      return this.wot.wtViewport.columnsVisibleCalculator.count;
    }
  }, {
    key: 'allColumnsInViewport',
    value: function allColumnsInViewport() {
      return this.wot.getSetting('totalColumns') == this.getVisibleColumnsCount();
    }
  }, {
    key: 'getColumnWidth',
    value: function getColumnWidth(sourceColumn) {
      var width = this.wot.wtSettings.settings.columnWidth;

      if (typeof width === 'function') {
        width = width(sourceColumn);
      } else if ((typeof width === 'undefined' ? 'undefined' : _typeof(width)) === 'object') {
        width = width[sourceColumn];
      }

      return width || this.wot.wtSettings.settings.defaultColumnWidth;
    }
  }, {
    key: 'getStretchedColumnWidth',
    value: function getStretchedColumnWidth(sourceColumn) {
      var columnWidth = this.getColumnWidth(sourceColumn);
      var width = columnWidth == null ? this.instance.wtSettings.settings.defaultColumnWidth : columnWidth;
      var calculator = this.wot.wtViewport.columnsRenderCalculator;

      if (calculator) {
        var stretchedWidth = calculator.getStretchedColumnWidth(sourceColumn, width);

        if (stretchedWidth) {
          width = stretchedWidth;
        }
      }

      return width;
    }

    /**
     * Modify row header widths provided by user in class contructor.
     *
     * @private
     */

  }, {
    key: '_modifyRowHeaderWidth',
    value: function _modifyRowHeaderWidth(rowHeaderWidthFactory) {
      var widths = (0, _function.isFunction)(rowHeaderWidthFactory) ? rowHeaderWidthFactory() : null;

      if (Array.isArray(widths)) {
        widths = [].concat(_toConsumableArray(widths));
        widths[widths.length - 1] = this._correctRowHeaderWidth(widths[widths.length - 1]);
      } else {
        widths = this._correctRowHeaderWidth(widths);
      }

      return widths;
    }

    /**
     * Correct row header width if necessary.
     *
     * @private
     */

  }, {
    key: '_correctRowHeaderWidth',
    value: function _correctRowHeaderWidth(width) {
      if (typeof width !== 'number') {
        width = this.wot.getSetting('defaultColumnWidth');
      }
      if (this.correctHeaderWidth) {
        width++;
      }

      return width;
    }
  }]);

  return Table;
}();

exports.default = Table;

/***/ }),
/* 261 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


exports.__esModule = true;

var _createClass = 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); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

var _element = __webpack_require__(0);

var _base = __webpack_require__(29);

var _base2 = _interopRequireDefault(_base);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

var performanceWarningAppeared = false;

/**
 * @class TableRenderer
 */

var TableRenderer = function () {
  /**
   * @param {WalkontableTable} wtTable
   */
  function TableRenderer(wtTable) {
    _classCallCheck(this, TableRenderer);

    this.wtTable = wtTable;
    this.wot = wtTable.instance;

    // legacy support
    this.instance = wtTable.instance;

    this.rowFilter = wtTable.rowFilter;
    this.columnFilter = wtTable.columnFilter;

    this.TABLE = wtTable.TABLE;
    this.THEAD = wtTable.THEAD;
    this.TBODY = wtTable.TBODY;
    this.COLGROUP = wtTable.COLGROUP;

    this.rowHeaders = [];
    this.rowHeaderCount = 0;
    this.columnHeaders = [];
    this.columnHeaderCount = 0;
    this.fixedRowsTop = 0;
    this.fixedRowsBottom = 0;
  }

  /**
   *
   */


  _createClass(TableRenderer, [{
    key: 'render',
    value: function render() {
      if (!this.wtTable.isWorkingOnClone()) {
        var skipRender = {};
        this.wot.getSetting('beforeDraw', true, skipRender);

        if (skipRender.skipRender === true) {
          return;
        }
      }

      this.rowHeaders = this.wot.getSetting('rowHeaders');
      this.rowHeaderCount = this.rowHeaders.length;
      this.fixedRowsTop = this.wot.getSetting('fixedRowsTop');
      this.fixedRowsBottom = this.wot.getSetting('fixedRowsBottom');
      this.columnHeaders = this.wot.getSetting('columnHeaders');
      this.columnHeaderCount = this.columnHeaders.length;

      var columnsToRender = this.wtTable.getRenderedColumnsCount();
      var rowsToRender = this.wtTable.getRenderedRowsCount();
      var totalColumns = this.wot.getSetting('totalColumns');
      var totalRows = this.wot.getSetting('totalRows');
      var workspaceWidth = void 0;
      var adjusted = false;

      if (_base2.default.isOverlayTypeOf(this.wot.cloneOverlay, _base2.default.CLONE_BOTTOM) || _base2.default.isOverlayTypeOf(this.wot.cloneOverlay, _base2.default.CLONE_BOTTOM_LEFT_CORNER)) {

        // do NOT render headers on the bottom or bottom-left corner overlay
        this.columnHeaders = [];
        this.columnHeaderCount = 0;
      }

      if (totalColumns >= 0) {
        // prepare COL and TH elements for rendering
        this.adjustAvailableNodes();
        adjusted = true;

        // adjust column widths according to user widths settings
        this.renderColumnHeaders();

        // Render table rows
        this.renderRows(totalRows, rowsToRender, columnsToRender);

        if (!this.wtTable.isWorkingOnClone()) {
          workspaceWidth = this.wot.wtViewport.getWorkspaceWidth();
          this.wot.wtViewport.containerWidth = null;
        }

        this.adjustColumnWidths(columnsToRender);
        this.markOversizedColumnHeaders();
        this.adjustColumnHeaderHeights();
      }

      if (!adjusted) {
        this.adjustAvailableNodes();
      }
      this.removeRedundantRows(rowsToRender);

      if (!this.wtTable.isWorkingOnClone() || this.wot.isOverlayName(_base2.default.CLONE_BOTTOM)) {
        this.markOversizedRows();
      }
      if (!this.wtTable.isWorkingOnClone()) {
        this.wot.wtViewport.createVisibleCalculators();
        this.wot.wtOverlays.refresh(false);

        this.wot.wtOverlays.applyToDOM();

        var hiderWidth = (0, _element.outerWidth)(this.wtTable.hider);
        var tableWidth = (0, _element.outerWidth)(this.wtTable.TABLE);

        if (hiderWidth !== 0 && tableWidth !== hiderWidth) {
          // Recalculate the column widths, if width changes made in the overlays removed the scrollbar, thus changing the viewport width.
          this.adjustColumnWidths(columnsToRender);
        }

        if (workspaceWidth !== this.wot.wtViewport.getWorkspaceWidth()) {
          // workspace width changed though to shown/hidden vertical scrollbar. Let's reapply stretching
          this.wot.wtViewport.containerWidth = null;

          var firstRendered = this.wtTable.getFirstRenderedColumn();
          var lastRendered = this.wtTable.getLastRenderedColumn();
          var defaultColumnWidth = this.wot.getSetting('defaultColumnWidth');
          var rowHeaderWidthSetting = this.wot.getSetting('rowHeaderWidth');

          rowHeaderWidthSetting = this.instance.getSetting('onModifyRowHeaderWidth', rowHeaderWidthSetting);

          if (rowHeaderWidthSetting != null) {
            for (var i = 0; i < this.rowHeaderCount; i++) {
              var width = Array.isArray(rowHeaderWidthSetting) ? rowHeaderWidthSetting[i] : rowHeaderWidthSetting;

              width = width == null ? defaultColumnWidth : width;

              this.COLGROUP.childNodes[i].style.width = width + 'px';
            }
          }

          for (var _i = firstRendered; _i < lastRendered; _i++) {
            var _width = this.wtTable.getStretchedColumnWidth(_i);
            var renderedIndex = this.columnFilter.sourceToRendered(_i);

            this.COLGROUP.childNodes[renderedIndex + this.rowHeaderCount].style.width = _width + 'px';
          }
        }

        this.wot.getSetting('onDraw', true);
      } else if (this.wot.isOverlayName(_base2.default.CLONE_BOTTOM)) {
        this.wot.cloneSource.wtOverlays.adjustElementsSize();
      }
    }

    /**
     * @param {Number} renderedRowsCount
     */

  }, {
    key: 'removeRedundantRows',
    value: function removeRedundantRows(renderedRowsCount) {
      while (this.wtTable.tbodyChildrenLength > renderedRowsCount) {
        this.TBODY.removeChild(this.TBODY.lastChild);
        this.wtTable.tbodyChildrenLength--;
      }
    }

    /**
     * @param {Number} totalRows
     * @param {Number} rowsToRender
     * @param {Number} columnsToRender
     */

  }, {
    key: 'renderRows',
    value: function renderRows(totalRows, rowsToRender, columnsToRender) {
      var lastTD = void 0,
          TR = void 0;
      var visibleRowIndex = 0;
      var sourceRowIndex = this.rowFilter.renderedToSource(visibleRowIndex);
      var isWorkingOnClone = this.wtTable.isWorkingOnClone();

      while (sourceRowIndex < totalRows && sourceRowIndex >= 0) {
        if (!performanceWarningAppeared && visibleRowIndex > 1000) {
          performanceWarningAppeared = true;
          console.warn('Performance tip: Handsontable rendered more than 1000 visible rows. Consider limiting the number ' + 'of rendered rows by specifying the table height and/or turning off the "renderAllRows" option.');
        }
        if (rowsToRender !== void 0 && visibleRowIndex === rowsToRender) {
          // We have as much rows as needed for this clone
          break;
        }
        TR = this.getOrCreateTrForRow(visibleRowIndex, TR);

        // Render row headers
        this.renderRowHeaders(sourceRowIndex, TR);
        // Add and/or remove TDs to TR to match the desired number
        this.adjustColumns(TR, columnsToRender + this.rowHeaderCount);

        lastTD = this.renderCells(sourceRowIndex, TR, columnsToRender);

        if (!isWorkingOnClone ||
        // Necessary to refresh oversized row heights after editing cell in overlays
        this.wot.isOverlayName(_base2.default.CLONE_BOTTOM)) {
          // Reset the oversized row cache for this row
          this.resetOversizedRow(sourceRowIndex);
        }

        if (TR.firstChild) {
          // if I have 2 fixed columns with one-line content and the 3rd column has a multiline content, this is
          // the way to make sure that the overlay will has same row height
          var height = this.wot.wtTable.getRowHeight(sourceRowIndex);

          if (height) {
            // Decrease height. 1 pixel will be "replaced" by 1px border top
            height--;
            TR.firstChild.style.height = height + 'px';
          } else {
            TR.firstChild.style.height = '';
          }
        }
        visibleRowIndex++;
        sourceRowIndex = this.rowFilter.renderedToSource(visibleRowIndex);
      }
    }

    /**
     * Reset the oversized row cache for the provided index
     *
     * @param {Number} sourceRow Row index
     */

  }, {
    key: 'resetOversizedRow',
    value: function resetOversizedRow(sourceRow) {
      if (this.wot.getSetting('externalRowCalculator')) {
        return;
      }
      if (this.wot.wtViewport.oversizedRows && this.wot.wtViewport.oversizedRows[sourceRow]) {
        this.wot.wtViewport.oversizedRows[sourceRow] = void 0;
      }
    }

    /**
     * Check if any of the rendered rows is higher than expected, and if so, cache them
     */

  }, {
    key: 'markOversizedRows',
    value: function markOversizedRows() {
      if (this.wot.getSetting('externalRowCalculator')) {
        return;
      }
      var rowCount = this.instance.wtTable.TBODY.childNodes.length;
      var expectedTableHeight = rowCount * this.instance.wtSettings.settings.defaultRowHeight;
      var actualTableHeight = (0, _element.innerHeight)(this.instance.wtTable.TBODY) - 1;
      var previousRowHeight = void 0;
      var rowInnerHeight = void 0;
      var sourceRowIndex = void 0;
      var currentTr = void 0;
      var rowHeader = void 0;
      var totalRows = this.instance.getSetting('totalRows');

      if (expectedTableHeight === actualTableHeight && !this.instance.getSetting('fixedRowsBottom')) {
        // If the actual table height equals rowCount * default single row height, no row is oversized -> no need to iterate over them
        return;
      }

      while (rowCount) {
        rowCount--;
        sourceRowIndex = this.instance.wtTable.rowFilter.renderedToSource(rowCount);
        previousRowHeight = this.instance.wtTable.getRowHeight(sourceRowIndex);
        currentTr = this.instance.wtTable.getTrForRow(sourceRowIndex);
        rowHeader = currentTr.querySelector('th');

        if (rowHeader) {
          rowInnerHeight = (0, _element.innerHeight)(rowHeader);
        } else {
          rowInnerHeight = (0, _element.innerHeight)(currentTr) - 1;
        }

        if (!previousRowHeight && this.instance.wtSettings.settings.defaultRowHeight < rowInnerHeight || previousRowHeight < rowInnerHeight) {
          this.instance.wtViewport.oversizedRows[sourceRowIndex] = ++rowInnerHeight;
        }
      }
    }

    /**
     * Check if any of the rendered columns is higher than expected, and if so, cache them.
     */

  }, {
    key: 'markOversizedColumnHeaders',
    value: function markOversizedColumnHeaders() {
      var overlayName = this.wot.getOverlayName();

      if (!this.columnHeaderCount || this.wot.wtViewport.hasOversizedColumnHeadersMarked[overlayName] || this.wtTable.isWorkingOnClone()) {
        return;
      }
      var columnCount = this.wtTable.getRenderedColumnsCount();

      for (var i = 0; i < this.columnHeaderCount; i++) {
        for (var renderedColumnIndex = -1 * this.rowHeaderCount; renderedColumnIndex < columnCount; renderedColumnIndex++) {
          this.markIfOversizedColumnHeader(renderedColumnIndex);
        }
      }
      this.wot.wtViewport.hasOversizedColumnHeadersMarked[overlayName] = true;
    }

    /**
     *
     */

  }, {
    key: 'adjustColumnHeaderHeights',
    value: function adjustColumnHeaderHeights() {
      var columnHeaders = this.wot.getSetting('columnHeaders');
      var children = this.wot.wtTable.THEAD.childNodes;
      var oversizedColumnHeaders = this.wot.wtViewport.oversizedColumnHeaders;

      for (var i = 0, len = columnHeaders.length; i < len; i++) {
        if (oversizedColumnHeaders[i]) {
          if (!children[i] || children[i].childNodes.length === 0) {
            return;
          }
          children[i].childNodes[0].style.height = oversizedColumnHeaders[i] + 'px';
        }
      }
    }

    /**
     * Check if column header for the specified column is higher than expected, and if so, cache it
     *
     * @param {Number} col Index of column
     */

  }, {
    key: 'markIfOversizedColumnHeader',
    value: function markIfOversizedColumnHeader(col) {
      var sourceColIndex = this.wot.wtTable.columnFilter.renderedToSource(col);
      var level = this.columnHeaderCount;
      var defaultRowHeight = this.wot.wtSettings.settings.defaultRowHeight;
      var previousColHeaderHeight = void 0;
      var currentHeader = void 0;
      var currentHeaderHeight = void 0;
      var columnHeaderHeightSetting = this.wot.getSetting('columnHeaderHeight') || [];

      while (level) {
        level--;

        previousColHeaderHeight = this.wot.wtTable.getColumnHeaderHeight(level);
        currentHeader = this.wot.wtTable.getColumnHeader(sourceColIndex, level);

        if (!currentHeader) {
          /* eslint-disable no-continue */
          continue;
        }
        currentHeaderHeight = (0, _element.innerHeight)(currentHeader);

        if (!previousColHeaderHeight && defaultRowHeight < currentHeaderHeight || previousColHeaderHeight < currentHeaderHeight) {
          this.wot.wtViewport.oversizedColumnHeaders[level] = currentHeaderHeight;
        }

        if (Array.isArray(columnHeaderHeightSetting)) {
          if (columnHeaderHeightSetting[level] != null) {
            this.wot.wtViewport.oversizedColumnHeaders[level] = columnHeaderHeightSetting[level];
          }
        } else if (!isNaN(columnHeaderHeightSetting)) {
          this.wot.wtViewport.oversizedColumnHeaders[level] = columnHeaderHeightSetting;
        }

        if (this.wot.wtViewport.oversizedColumnHeaders[level] < (columnHeaderHeightSetting[level] || columnHeaderHeightSetting)) {
          this.wot.wtViewport.oversizedColumnHeaders[level] = columnHeaderHeightSetting[level] || columnHeaderHeightSetting;
        }
      }
    }

    /**
     * @param {Number} sourceRowIndex
     * @param {HTMLTableRowElement} TR
     * @param {Number} columnsToRender
     * @returns {HTMLTableCellElement}
     */

  }, {
    key: 'renderCells',
    value: function renderCells(sourceRowIndex, TR, columnsToRender) {
      var TD = void 0;
      var sourceColIndex = void 0;

      for (var visibleColIndex = 0; visibleColIndex < columnsToRender; visibleColIndex++) {
        sourceColIndex = this.columnFilter.renderedToSource(visibleColIndex);

        if (visibleColIndex === 0) {
          TD = TR.childNodes[this.columnFilter.sourceColumnToVisibleRowHeadedColumn(sourceColIndex)];
        } else {
          TD = TD.nextSibling; // http://jsperf.com/nextsibling-vs-indexed-childnodes
        }
        // If the number of headers has been reduced, we need to replace excess TH with TD
        if (TD.nodeName == 'TH') {
          TD = replaceThWithTd(TD, TR);
        }
        if (!(0, _element.hasClass)(TD, 'hide')) {
          TD.className = '';
        }
        TD.removeAttribute('style');
        this.wot.wtSettings.settings.cellRenderer(sourceRowIndex, sourceColIndex, TD);
      }

      return TD;
    }

    /**
     * @param {Number} columnsToRender Number of columns to render.
     */

  }, {
    key: 'adjustColumnWidths',
    value: function adjustColumnWidths(columnsToRender) {
      var scrollbarCompensation = 0;
      var sourceInstance = this.wot.cloneSource ? this.wot.cloneSource : this.wot;
      var mainHolder = sourceInstance.wtTable.holder;
      var defaultColumnWidth = this.wot.getSetting('defaultColumnWidth');
      var rowHeaderWidthSetting = this.wot.getSetting('rowHeaderWidth');

      if (mainHolder.offsetHeight < mainHolder.scrollHeight) {
        scrollbarCompensation = (0, _element.getScrollbarWidth)();
      }
      this.wot.wtViewport.columnsRenderCalculator.refreshStretching(this.wot.wtViewport.getViewportWidth() - scrollbarCompensation);

      rowHeaderWidthSetting = this.instance.getSetting('onModifyRowHeaderWidth', rowHeaderWidthSetting);

      if (rowHeaderWidthSetting != null) {
        for (var i = 0; i < this.rowHeaderCount; i++) {
          var width = Array.isArray(rowHeaderWidthSetting) ? rowHeaderWidthSetting[i] : rowHeaderWidthSetting;

          width = width == null ? defaultColumnWidth : width;

          this.COLGROUP.childNodes[i].style.width = width + 'px';
        }
      }

      for (var renderedColIndex = 0; renderedColIndex < columnsToRender; renderedColIndex++) {
        var _width2 = this.wtTable.getStretchedColumnWidth(this.columnFilter.renderedToSource(renderedColIndex));

        this.COLGROUP.childNodes[renderedColIndex + this.rowHeaderCount].style.width = _width2 + 'px';
      }
    }

    /**
     * @param {HTMLTableCellElement} TR
     */

  }, {
    key: 'appendToTbody',
    value: function appendToTbody(TR) {
      this.TBODY.appendChild(TR);
      this.wtTable.tbodyChildrenLength++;
    }

    /**
     * @param {Number} rowIndex
     * @param {HTMLTableRowElement} currentTr
     * @returns {HTMLTableCellElement}
     */

  }, {
    key: 'getOrCreateTrForRow',
    value: function getOrCreateTrForRow(rowIndex, currentTr) {
      var TR = void 0;

      if (rowIndex >= this.wtTable.tbodyChildrenLength) {
        TR = this.createRow();
        this.appendToTbody(TR);
      } else if (rowIndex === 0) {
        TR = this.TBODY.firstChild;
      } else {
        // http://jsperf.com/nextsibling-vs-indexed-childnodes
        TR = currentTr.nextSibling;
      }
      if (TR.className) {
        TR.removeAttribute('class');
      }

      return TR;
    }

    /**
     * @returns {HTMLTableCellElement}
     */

  }, {
    key: 'createRow',
    value: function createRow() {
      var TR = document.createElement('TR');

      for (var visibleColIndex = 0; visibleColIndex < this.rowHeaderCount; visibleColIndex++) {
        TR.appendChild(document.createElement('TH'));
      }

      return TR;
    }

    /**
     * @param {Number} row
     * @param {Number} col
     * @param {HTMLTableCellElement} TH
     */

  }, {
    key: 'renderRowHeader',
    value: function renderRowHeader(row, col, TH) {
      TH.className = '';
      TH.removeAttribute('style');
      this.rowHeaders[col](row, TH, col);
    }

    /**
     * @param {Number} row
     * @param {HTMLTableCellElement} TR
     */

  }, {
    key: 'renderRowHeaders',
    value: function renderRowHeaders(row, TR) {
      for (var TH = TR.firstChild, visibleColIndex = 0; visibleColIndex < this.rowHeaderCount; visibleColIndex++) {
        // If the number of row headers increased we need to create TH or replace an existing TD node with TH
        if (!TH) {
          TH = document.createElement('TH');
          TR.appendChild(TH);
        } else if (TH.nodeName == 'TD') {
          TH = replaceTdWithTh(TH, TR);
        }
        this.renderRowHeader(row, visibleColIndex, TH);
        // http://jsperf.com/nextsibling-vs-indexed-childnodes
        TH = TH.nextSibling;
      }
    }

    /**
     * Adjust the number of COL and TH elements to match the number of columns and headers that need to be rendered
     */

  }, {
    key: 'adjustAvailableNodes',
    value: function adjustAvailableNodes() {
      this.adjustColGroups();
      this.adjustThead();
    }

    /**
     * Renders the column headers
     */

  }, {
    key: 'renderColumnHeaders',
    value: function renderColumnHeaders() {
      if (!this.columnHeaderCount) {
        return;
      }
      var columnCount = this.wtTable.getRenderedColumnsCount();

      for (var i = 0; i < this.columnHeaderCount; i++) {
        var TR = this.getTrForColumnHeaders(i);

        for (var renderedColumnIndex = -1 * this.rowHeaderCount; renderedColumnIndex < columnCount; renderedColumnIndex++) {
          var sourceCol = this.columnFilter.renderedToSource(renderedColumnIndex);

          this.renderColumnHeader(i, sourceCol, TR.childNodes[renderedColumnIndex + this.rowHeaderCount]);
        }
      }
    }

    /**
     * Adjusts the number of COL elements to match the number of columns that need to be rendered
     */

  }, {
    key: 'adjustColGroups',
    value: function adjustColGroups() {
      var columnCount = this.wtTable.getRenderedColumnsCount();

      while (this.wtTable.colgroupChildrenLength < columnCount + this.rowHeaderCount) {
        this.COLGROUP.appendChild(document.createElement('COL'));
        this.wtTable.colgroupChildrenLength++;
      }
      while (this.wtTable.colgroupChildrenLength > columnCount + this.rowHeaderCount) {
        this.COLGROUP.removeChild(this.COLGROUP.lastChild);
        this.wtTable.colgroupChildrenLength--;
      }
      if (this.rowHeaderCount) {
        (0, _element.addClass)(this.COLGROUP.childNodes[0], 'rowHeader');
      }
    }

    /**
     * Adjusts the number of TH elements in THEAD to match the number of headers and columns that need to be rendered
     */

  }, {
    key: 'adjustThead',
    value: function adjustThead() {
      var columnCount = this.wtTable.getRenderedColumnsCount();
      var TR = this.THEAD.firstChild;

      if (this.columnHeaders.length) {
        for (var i = 0, len = this.columnHeaders.length; i < len; i++) {
          TR = this.THEAD.childNodes[i];

          if (!TR) {
            TR = document.createElement('TR');
            this.THEAD.appendChild(TR);
          }
          this.theadChildrenLength = TR.childNodes.length;

          while (this.theadChildrenLength < columnCount + this.rowHeaderCount) {
            TR.appendChild(document.createElement('TH'));
            this.theadChildrenLength++;
          }
          while (this.theadChildrenLength > columnCount + this.rowHeaderCount) {
            TR.removeChild(TR.lastChild);
            this.theadChildrenLength--;
          }
        }
        var theadChildrenLength = this.THEAD.childNodes.length;

        if (theadChildrenLength > this.columnHeaders.length) {
          for (var _i2 = this.columnHeaders.length; _i2 < theadChildrenLength; _i2++) {
            this.THEAD.removeChild(this.THEAD.lastChild);
          }
        }
      } else if (TR) {
        (0, _element.empty)(TR);
      }
    }

    /**
     * @param {Number} index
     * @returns {HTMLTableCellElement}
     */

  }, {
    key: 'getTrForColumnHeaders',
    value: function getTrForColumnHeaders(index) {
      return this.THEAD.childNodes[index];
    }

    /**
     * @param {Number} row
     * @param {Number} col
     * @param {HTMLTableCellElement} TH
     * @returns {*}
     */

  }, {
    key: 'renderColumnHeader',
    value: function renderColumnHeader(row, col, TH) {
      TH.className = '';
      TH.removeAttribute('style');

      return this.columnHeaders[row](col, TH, row);
    }

    /**
     * Add and/or remove the TDs to match the desired number
     *
     * @param {HTMLTableCellElement} TR Table row in question
     * @param {Number} desiredCount The desired number of TDs in the TR
     */

  }, {
    key: 'adjustColumns',
    value: function adjustColumns(TR, desiredCount) {
      var count = TR.childNodes.length;

      while (count < desiredCount) {
        var TD = document.createElement('TD');

        TR.appendChild(TD);
        count++;
      }
      while (count > desiredCount) {
        TR.removeChild(TR.lastChild);
        count--;
      }
    }

    /**
     * @param {Number} columnsToRender
     */

  }, {
    key: 'removeRedundantColumns',
    value: function removeRedundantColumns(columnsToRender) {
      while (this.wtTable.tbodyChildrenLength > columnsToRender) {
        this.TBODY.removeChild(this.TBODY.lastChild);
        this.wtTable.tbodyChildrenLength--;
      }
    }
  }]);

  return TableRenderer;
}();

function replaceTdWithTh(TD, TR) {
  var TH = document.createElement('TH');

  TR.insertBefore(TH, TD);
  TR.removeChild(TD);

  return TH;
}

function replaceThWithTd(TH, TR) {
  var TD = document.createElement('TD');

  TR.insertBefore(TD, TH);
  TR.removeChild(TH);

  return TD;
}

exports.default = TableRenderer;

/***/ }),
/* 262 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


exports.__esModule = true;

var _createClass = 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); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

var _element = __webpack_require__(0);

var _object = __webpack_require__(3);

var _eventManager = __webpack_require__(4);

var _eventManager2 = _interopRequireDefault(_eventManager);

var _viewportColumns = __webpack_require__(251);

var _viewportColumns2 = _interopRequireDefault(_viewportColumns);

var _viewportRows = __webpack_require__(252);

var _viewportRows2 = _interopRequireDefault(_viewportRows);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

/**
 * @class Viewport
 */
var Viewport = function () {
  /**
   * @param wotInstance
   */
  function Viewport(wotInstance) {
    var _this = this;

    _classCallCheck(this, Viewport);

    this.wot = wotInstance;
    // legacy support
    this.instance = this.wot;

    this.oversizedRows = [];
    this.oversizedColumnHeaders = [];
    this.hasOversizedColumnHeadersMarked = {};
    this.clientHeight = 0;
    this.containerWidth = NaN;
    this.rowHeaderWidth = NaN;
    this.rowsVisibleCalculator = null;
    this.columnsVisibleCalculator = null;

    this.eventManager = new _eventManager2.default(this.wot);
    this.eventManager.addEventListener(window, 'resize', function () {
      _this.clientHeight = _this.getWorkspaceHeight();
    });
  }

  /**
   * @returns {number}
   */


  _createClass(Viewport, [{
    key: 'getWorkspaceHeight',
    value: function getWorkspaceHeight() {
      var trimmingContainer = this.instance.wtOverlays.topOverlay.trimmingContainer;
      var elemHeight = void 0;
      var height = 0;

      if (trimmingContainer === window) {
        height = document.documentElement.clientHeight;
      } else {
        elemHeight = (0, _element.outerHeight)(trimmingContainer);
        // returns height without DIV scrollbar
        height = elemHeight > 0 && trimmingContainer.clientHeight > 0 ? trimmingContainer.clientHeight : Infinity;
      }

      return height;
    }
  }, {
    key: 'getWorkspaceWidth',
    value: function getWorkspaceWidth() {
      var width = void 0;
      var totalColumns = this.wot.getSetting('totalColumns');
      var trimmingContainer = this.instance.wtOverlays.leftOverlay.trimmingContainer;
      var overflow = void 0;
      var stretchSetting = this.wot.getSetting('stretchH');
      var docOffsetWidth = document.documentElement.offsetWidth;
      var preventOverflow = this.wot.getSetting('preventOverflow');

      if (preventOverflow) {
        return (0, _element.outerWidth)(this.instance.wtTable.wtRootElement);
      }

      if (this.wot.getSetting('freezeOverlays')) {
        width = Math.min(docOffsetWidth - this.getWorkspaceOffset().left, docOffsetWidth);
      } else {
        width = Math.min(this.getContainerFillWidth(), docOffsetWidth - this.getWorkspaceOffset().left, docOffsetWidth);
      }

      if (trimmingContainer === window && totalColumns > 0 && this.sumColumnWidths(0, totalColumns - 1) > width) {
        // in case sum of column widths is higher than available stylesheet width, let's assume using the whole window
        // otherwise continue below, which will allow stretching
        // this is used in `scroll_window.html`
        // TODO test me
        return document.documentElement.clientWidth;
      }

      if (trimmingContainer !== window) {
        overflow = (0, _element.getStyle)(this.instance.wtOverlays.leftOverlay.trimmingContainer, 'overflow');

        if (overflow == 'scroll' || overflow == 'hidden' || overflow == 'auto') {
          // this is used in `scroll.html`
          // TODO test me
          return Math.max(width, trimmingContainer.clientWidth);
        }
      }

      if (stretchSetting === 'none' || !stretchSetting) {
        // if no stretching is used, return the maximum used workspace width
        return Math.max(width, (0, _element.outerWidth)(this.instance.wtTable.TABLE));
      }

      // if stretching is used, return the actual container width, so the columns can fit inside it
      return width;
    }

    /**
     * Checks if viewport has vertical scroll
     *
     * @returns {Boolean}
     */

  }, {
    key: 'hasVerticalScroll',
    value: function hasVerticalScroll() {
      return this.getWorkspaceActualHeight() > this.getWorkspaceHeight();
    }

    /**
     * Checks if viewport has horizontal scroll
     *
     * @returns {Boolean}
     */

  }, {
    key: 'hasHorizontalScroll',
    value: function hasHorizontalScroll() {
      return this.getWorkspaceActualWidth() > this.getWorkspaceWidth();
    }

    /**
     * @param from
     * @param length
     * @returns {Number}
     */

  }, {
    key: 'sumColumnWidths',
    value: function sumColumnWidths(from, length) {
      var sum = 0;

      while (from < length) {
        sum += this.wot.wtTable.getColumnWidth(from);
        from++;
      }

      return sum;
    }

    /**
     * @returns {Number}
     */

  }, {
    key: 'getContainerFillWidth',
    value: function getContainerFillWidth() {
      if (this.containerWidth) {
        return this.containerWidth;
      }
      var mainContainer = this.instance.wtTable.holder;
      var fillWidth = void 0;
      var dummyElement = void 0;

      dummyElement = document.createElement('div');
      dummyElement.style.width = '100%';
      dummyElement.style.height = '1px';
      mainContainer.appendChild(dummyElement);
      fillWidth = dummyElement.offsetWidth;

      this.containerWidth = fillWidth;
      mainContainer.removeChild(dummyElement);

      return fillWidth;
    }

    /**
     * @returns {Number}
     */

  }, {
    key: 'getWorkspaceOffset',
    value: function getWorkspaceOffset() {
      return (0, _element.offset)(this.wot.wtTable.TABLE);
    }

    /**
     * @returns {Number}
     */

  }, {
    key: 'getWorkspaceActualHeight',
    value: function getWorkspaceActualHeight() {
      return (0, _element.outerHeight)(this.wot.wtTable.TABLE);
    }

    /**
     * @returns {Number}
     */

  }, {
    key: 'getWorkspaceActualWidth',
    value: function getWorkspaceActualWidth() {
      return (0, _element.outerWidth)(this.wot.wtTable.TABLE) || (0, _element.outerWidth)(this.wot.wtTable.TBODY) || (0, _element.outerWidth)(this.wot.wtTable.THEAD); // IE8 reports 0 as <table> offsetWidth;
    }

    /**
     * @returns {Number}
     */

  }, {
    key: 'getColumnHeaderHeight',
    value: function getColumnHeaderHeight() {
      if (isNaN(this.columnHeaderHeight)) {
        this.columnHeaderHeight = (0, _element.outerHeight)(this.wot.wtTable.THEAD);
      }

      return this.columnHeaderHeight;
    }

    /**
     * @returns {Number}
     */

  }, {
    key: 'getViewportHeight',
    value: function getViewportHeight() {
      var containerHeight = this.getWorkspaceHeight();
      var columnHeaderHeight = void 0;

      if (containerHeight === Infinity) {
        return containerHeight;
      }
      columnHeaderHeight = this.getColumnHeaderHeight();

      if (columnHeaderHeight > 0) {
        containerHeight -= columnHeaderHeight;
      }

      return containerHeight;
    }

    /**
     * @returns {Number}
     */

  }, {
    key: 'getRowHeaderWidth',
    value: function getRowHeaderWidth() {
      var rowHeadersHeightSetting = this.instance.getSetting('rowHeaderWidth');
      var rowHeaders = this.instance.getSetting('rowHeaders');

      if (rowHeadersHeightSetting) {
        this.rowHeaderWidth = 0;

        for (var i = 0, len = rowHeaders.length; i < len; i++) {
          this.rowHeaderWidth += rowHeadersHeightSetting[i] || rowHeadersHeightSetting;
        }
      }

      if (this.wot.cloneSource) {
        return this.wot.cloneSource.wtViewport.getRowHeaderWidth();
      }

      if (isNaN(this.rowHeaderWidth)) {

        if (rowHeaders.length) {
          var TH = this.instance.wtTable.TABLE.querySelector('TH');
          this.rowHeaderWidth = 0;

          for (var _i = 0, _len = rowHeaders.length; _i < _len; _i++) {
            if (TH) {
              this.rowHeaderWidth += (0, _element.outerWidth)(TH);
              TH = TH.nextSibling;
            } else {
              // yes this is a cheat but it worked like that before, just taking assumption from CSS instead of measuring.
              // TODO: proper fix
              this.rowHeaderWidth += 50;
            }
          }
        } else {
          this.rowHeaderWidth = 0;
        }
      }

      this.rowHeaderWidth = this.instance.getSetting('onModifyRowHeaderWidth', this.rowHeaderWidth) || this.rowHeaderWidth;

      return this.rowHeaderWidth;
    }

    /**
     * @returns {Number}
     */

  }, {
    key: 'getViewportWidth',
    value: function getViewportWidth() {
      var containerWidth = this.getWorkspaceWidth();
      var rowHeaderWidth = void 0;

      if (containerWidth === Infinity) {
        return containerWidth;
      }
      rowHeaderWidth = this.getRowHeaderWidth();

      if (rowHeaderWidth > 0) {
        return containerWidth - rowHeaderWidth;
      }

      return containerWidth;
    }

    /**
     * Creates:
     *  - rowsRenderCalculator (before draw, to qualify rows for rendering)
     *  - rowsVisibleCalculator (after draw, to measure which rows are actually visible)
     *
     * @returns {ViewportRowsCalculator}
     */

  }, {
    key: 'createRowsCalculator',
    value: function createRowsCalculator() {
      var _this2 = this;

      var visible = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;

      var height = void 0;
      var pos = void 0;
      var fixedRowsTop = void 0;
      var scrollbarHeight = void 0;
      var fixedRowsBottom = void 0;
      var fixedRowsHeight = void 0;
      var totalRows = void 0;

      this.rowHeaderWidth = NaN;

      if (this.wot.wtSettings.settings.renderAllRows) {
        height = Infinity;
      } else {
        height = this.getViewportHeight();
      }
      pos = this.wot.wtOverlays.topOverlay.getScrollPosition() - this.wot.wtOverlays.topOverlay.getTableParentOffset();

      if (pos < 0) {
        pos = 0;
      }
      fixedRowsTop = this.wot.getSetting('fixedRowsTop');
      fixedRowsBottom = this.wot.getSetting('fixedRowsBottom');
      totalRows = this.wot.getSetting('totalRows');

      if (fixedRowsTop) {
        fixedRowsHeight = this.wot.wtOverlays.topOverlay.sumCellSizes(0, fixedRowsTop);
        pos += fixedRowsHeight;
        height -= fixedRowsHeight;
      }

      if (fixedRowsBottom && this.wot.wtOverlays.bottomOverlay.clone) {
        fixedRowsHeight = this.wot.wtOverlays.bottomOverlay.sumCellSizes(totalRows - fixedRowsBottom, totalRows);

        height -= fixedRowsHeight;
      }

      if (this.wot.wtTable.holder.clientHeight === this.wot.wtTable.holder.offsetHeight) {
        scrollbarHeight = 0;
      } else {
        scrollbarHeight = (0, _element.getScrollbarWidth)();
      }

      return new _viewportRows2.default(height, pos, this.wot.getSetting('totalRows'), function (sourceRow) {
        return _this2.wot.wtTable.getRowHeight(sourceRow);
      }, visible ? null : this.wot.wtSettings.settings.viewportRowCalculatorOverride, visible, scrollbarHeight);
    }

    /**
     * Creates:
     *  - columnsRenderCalculator (before draw, to qualify columns for rendering)
     *  - columnsVisibleCalculator (after draw, to measure which columns are actually visible)
     *
     * @returns {ViewportRowsCalculator}
     */

  }, {
    key: 'createColumnsCalculator',
    value: function createColumnsCalculator() {
      var _this3 = this;

      var visible = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;

      var width = this.getViewportWidth();
      var pos = void 0;
      var fixedColumnsLeft = void 0;

      this.columnHeaderHeight = NaN;

      pos = this.wot.wtOverlays.leftOverlay.getScrollPosition() - this.wot.wtOverlays.leftOverlay.getTableParentOffset();

      if (pos < 0) {
        pos = 0;
      }
      fixedColumnsLeft = this.wot.getSetting('fixedColumnsLeft');

      if (fixedColumnsLeft) {
        var fixedColumnsWidth = this.wot.wtOverlays.leftOverlay.sumCellSizes(0, fixedColumnsLeft);
        pos += fixedColumnsWidth;
        width -= fixedColumnsWidth;
      }
      if (this.wot.wtTable.holder.clientWidth !== this.wot.wtTable.holder.offsetWidth) {
        width -= (0, _element.getScrollbarWidth)();
      }

      return new _viewportColumns2.default(width, pos, this.wot.getSetting('totalColumns'), function (sourceCol) {
        return _this3.wot.wtTable.getColumnWidth(sourceCol);
      }, visible ? null : this.wot.wtSettings.settings.viewportColumnCalculatorOverride, visible, this.wot.getSetting('stretchH'), function (stretchedWidth, column) {
        return _this3.wot.getSetting('onBeforeStretchingColumnWidth', stretchedWidth, column);
      });
    }

    /**
     * Creates rowsRenderCalculator and columnsRenderCalculator (before draw, to determine what rows and
     * cols should be rendered)
     *
     * @param fastDraw {Boolean} If `true`, will try to avoid full redraw and only update the border positions.
     *                           If `false` or `undefined`, will perform a full redraw
     * @returns fastDraw {Boolean} The fastDraw value, possibly modified
     */

  }, {
    key: 'createRenderCalculators',
    value: function createRenderCalculators() {
      var fastDraw = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;

      if (fastDraw) {
        var proposedRowsVisibleCalculator = this.createRowsCalculator(true);
        var proposedColumnsVisibleCalculator = this.createColumnsCalculator(true);

        if (!(this.areAllProposedVisibleRowsAlreadyRendered(proposedRowsVisibleCalculator) && this.areAllProposedVisibleColumnsAlreadyRendered(proposedColumnsVisibleCalculator))) {
          fastDraw = false;
        }
      }

      if (!fastDraw) {
        this.rowsRenderCalculator = this.createRowsCalculator();
        this.columnsRenderCalculator = this.createColumnsCalculator();
      }
      // delete temporarily to make sure that renderers always use rowsRenderCalculator, not rowsVisibleCalculator
      this.rowsVisibleCalculator = null;
      this.columnsVisibleCalculator = null;

      return fastDraw;
    }

    /**
     * Creates rowsVisibleCalculator and columnsVisibleCalculator (after draw, to determine what are
     * the actually visible rows and columns)
     */

  }, {
    key: 'createVisibleCalculators',
    value: function createVisibleCalculators() {
      this.rowsVisibleCalculator = this.createRowsCalculator(true);
      this.columnsVisibleCalculator = this.createColumnsCalculator(true);
    }

    /**
     * Returns information whether proposedRowsVisibleCalculator viewport
     * is contained inside rows rendered in previous draw (cached in rowsRenderCalculator)
     *
     * @param {Object} proposedRowsVisibleCalculator
     * @returns {Boolean} Returns `true` if all proposed visible rows are already rendered (meaning: redraw is not needed).
     *                    Returns `false` if at least one proposed visible row is not already rendered (meaning: redraw is needed)
     */

  }, {
    key: 'areAllProposedVisibleRowsAlreadyRendered',
    value: function areAllProposedVisibleRowsAlreadyRendered(proposedRowsVisibleCalculator) {
      if (this.rowsVisibleCalculator) {
        if (proposedRowsVisibleCalculator.startRow < this.rowsRenderCalculator.startRow || proposedRowsVisibleCalculator.startRow === this.rowsRenderCalculator.startRow && proposedRowsVisibleCalculator.startRow > 0) {
          return false;
        } else if (proposedRowsVisibleCalculator.endRow > this.rowsRenderCalculator.endRow || proposedRowsVisibleCalculator.endRow === this.rowsRenderCalculator.endRow && proposedRowsVisibleCalculator.endRow < this.wot.getSetting('totalRows') - 1) {
          return false;
        }
        return true;
      }

      return false;
    }

    /**
     * Returns information whether proposedColumnsVisibleCalculator viewport
     * is contained inside column rendered in previous draw (cached in columnsRenderCalculator)
     *
     * @param {Object} proposedColumnsVisibleCalculator
     * @returns {Boolean} Returns `true` if all proposed visible columns are already rendered (meaning: redraw is not needed).
     *                    Returns `false` if at least one proposed visible column is not already rendered (meaning: redraw is needed)
     */

  }, {
    key: 'areAllProposedVisibleColumnsAlreadyRendered',
    value: function areAllProposedVisibleColumnsAlreadyRendered(proposedColumnsVisibleCalculator) {
      if (this.columnsVisibleCalculator) {
        if (proposedColumnsVisibleCalculator.startColumn < this.columnsRenderCalculator.startColumn || proposedColumnsVisibleCalculator.startColumn === this.columnsRenderCalculator.startColumn && proposedColumnsVisibleCalculator.startColumn > 0) {
          return false;
        } else if (proposedColumnsVisibleCalculator.endColumn > this.columnsRenderCalculator.endColumn || proposedColumnsVisibleCalculator.endColumn === this.columnsRenderCalculator.endColumn && proposedColumnsVisibleCalculator.endColumn < this.wot.getSetting('totalColumns') - 1) {
          return false;
        }
        return true;
      }

      return false;
    }

    /**
     * Resets values in keys of the hasOversizedColumnHeadersMarked object after updateSettings.
     */

  }, {
    key: 'resetHasOversizedColumnHeadersMarked',
    value: function resetHasOversizedColumnHeadersMarked() {
      (0, _object.objectEach)(this.hasOversizedColumnHeadersMarked, function (value, key, object) {
        object[key] = void 0;
      });
    }
  }]);

  return Viewport;
}();

exports.default = Viewport;

/***/ }),
/* 263 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


exports.__esModule = true;

var _unicode = __webpack_require__(15);

var _mixed = __webpack_require__(23);

var _string = __webpack_require__(28);

var _array = __webpack_require__(2);

var _element = __webpack_require__(0);

var _handsontableEditor = __webpack_require__(264);

var _handsontableEditor2 = _interopRequireDefault(_handsontableEditor);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

var AutocompleteEditor = _handsontableEditor2.default.prototype.extend();

/**
 * @private
 * @editor AutocompleteEditor
 * @class AutocompleteEditor
 * @dependencies HandsontableEditor
 */
AutocompleteEditor.prototype.init = function () {
  _handsontableEditor2.default.prototype.init.apply(this, arguments);
  this.query = null;
  this.strippedChoices = [];
  this.rawChoices = [];
};

AutocompleteEditor.prototype.getValue = function () {
  var _this2 = this;

  var selectedValue = this.rawChoices.find(function (value) {
    var strippedValue = _this2.stripValueIfNeeded(value);

    return strippedValue === _this2.TEXTAREA.value;
  });

  if ((0, _mixed.isDefined)(selectedValue)) {
    return selectedValue;
  }

  return this.TEXTAREA.value;
};

AutocompleteEditor.prototype.createElements = function () {
  _handsontableEditor2.default.prototype.createElements.apply(this, arguments);

  (0, _element.addClass)(this.htContainer, 'autocompleteEditor');
  (0, _element.addClass)(this.htContainer, window.navigator.platform.indexOf('Mac') === -1 ? '' : 'htMacScroll');
};

var skipOne = false;
function onBeforeKeyDown(event) {
  skipOne = false;
  var editor = this.getActiveEditor();

  if ((0, _unicode.isPrintableChar)(event.keyCode) || event.keyCode === _unicode.KEY_CODES.BACKSPACE || event.keyCode === _unicode.KEY_CODES.DELETE || event.keyCode === _unicode.KEY_CODES.INSERT) {
    var timeOffset = 0;

    // on ctl+c / cmd+c don't update suggestion list
    if (event.keyCode === _unicode.KEY_CODES.C && (event.ctrlKey || event.metaKey)) {
      return;
    }
    if (!editor.isOpened()) {
      timeOffset += 10;
    }

    if (editor.htEditor) {
      editor.instance._registerTimeout(setTimeout(function () {
        editor.queryChoices(editor.TEXTAREA.value);
        skipOne = true;
      }, timeOffset));
    }
  }
}

AutocompleteEditor.prototype.prepare = function () {
  this.instance.addHook('beforeKeyDown', onBeforeKeyDown);
  _handsontableEditor2.default.prototype.prepare.apply(this, arguments);
};

AutocompleteEditor.prototype.open = function () {
  // Ugly fix for handsontable which grab window object for autocomplete scroll listener instead table element.
  this.TEXTAREA_PARENT.style.overflow = 'auto';
  _handsontableEditor2.default.prototype.open.apply(this, arguments);
  this.TEXTAREA_PARENT.style.overflow = '';

  var choicesListHot = this.htEditor.getInstance();
  var _this = this;
  var trimDropdown = this.cellProperties.trimDropdown === void 0 ? true : this.cellProperties.trimDropdown;

  this.TEXTAREA.style.visibility = 'visible';
  this.focus();

  choicesListHot.updateSettings({
    colWidths: trimDropdown ? [(0, _element.outerWidth)(this.TEXTAREA) - 2] : void 0,
    width: trimDropdown ? (0, _element.outerWidth)(this.TEXTAREA) + (0, _element.getScrollbarWidth)() + 2 : void 0,
    afterRenderer: function afterRenderer(TD, row, col, prop, value, cellProperties) {
      var _this$cellProperties = _this.cellProperties,
          filteringCaseSensitive = _this$cellProperties.filteringCaseSensitive,
          allowHtml = _this$cellProperties.allowHtml;

      var indexOfMatch = void 0;
      var match = void 0;

      value = (0, _mixed.stringify)(value);

      if (value && !allowHtml) {
        indexOfMatch = filteringCaseSensitive === true ? value.indexOf(this.query) : value.toLowerCase().indexOf(_this.query.toLowerCase());

        if (indexOfMatch !== -1) {
          match = value.substr(indexOfMatch, _this.query.length);
          value = value.replace(match, '<strong>' + match + '</strong>');
        }
      }
      TD.innerHTML = value;
    },

    autoColumnSize: true,
    modifyColWidth: function modifyColWidth(width, col) {
      // workaround for <strong> text overlapping the dropdown, not really accurate
      var autoWidths = this.getPlugin('autoColumnSize').widths;

      if (autoWidths[col]) {
        width = autoWidths[col];
      }

      return trimDropdown ? width : width + 15;
    }
  });

  // Add additional space for autocomplete holder
  this.htEditor.view.wt.wtTable.holder.parentNode.style['padding-right'] = (0, _element.getScrollbarWidth)() + 2 + 'px';

  if (skipOne) {
    skipOne = false;
  }

  _this.instance._registerTimeout(setTimeout(function () {
    _this.queryChoices(_this.TEXTAREA.value);
  }, 0));
};

AutocompleteEditor.prototype.close = function () {
  _handsontableEditor2.default.prototype.close.apply(this, arguments);
};
AutocompleteEditor.prototype.queryChoices = function (query) {
  var _this3 = this;

  this.query = query;
  var source = this.cellProperties.source;

  if (typeof source == 'function') {
    source.call(this.cellProperties, query, function (choices) {
      _this3.rawChoices = choices;
      _this3.updateChoicesList(_this3.stripValuesIfNeeded(choices));
    });
  } else if (Array.isArray(source)) {
    this.rawChoices = source;
    this.updateChoicesList(this.stripValuesIfNeeded(source));
  } else {
    this.updateChoicesList([]);
  }
};

AutocompleteEditor.prototype.updateChoicesList = function (choices) {
  var pos = (0, _element.getCaretPosition)(this.TEXTAREA);
  var endPos = (0, _element.getSelectionEndPosition)(this.TEXTAREA);
  var sortByRelevanceSetting = this.cellProperties.sortByRelevance;
  var filterSetting = this.cellProperties.filter;
  var orderByRelevance = null;
  var highlightIndex = null;

  if (sortByRelevanceSetting) {
    orderByRelevance = AutocompleteEditor.sortByRelevance(this.stripValueIfNeeded(this.getValue()), choices, this.cellProperties.filteringCaseSensitive);
  }
  var orderByRelevanceLength = Array.isArray(orderByRelevance) ? orderByRelevance.length : 0;

  if (filterSetting === false) {
    if (orderByRelevanceLength) {
      highlightIndex = orderByRelevance[0];
    }
  } else {
    var sorted = [];

    for (var i = 0, choicesCount = choices.length; i < choicesCount; i++) {
      if (sortByRelevanceSetting && orderByRelevanceLength <= i) {
        break;
      }
      if (orderByRelevanceLength) {
        sorted.push(choices[orderByRelevance[i]]);
      } else {
        sorted.push(choices[i]);
      }
    }

    highlightIndex = 0;
    choices = sorted;
  }

  this.strippedChoices = choices;
  this.htEditor.loadData((0, _array.pivot)([choices]));

  this.updateDropdownHeight();

  this.flipDropdownIfNeeded();

  if (this.cellProperties.strict === true) {
    this.highlightBestMatchingChoice(highlightIndex);
  }

  this.instance.listen();
  this.TEXTAREA.focus();
  (0, _element.setCaretPosition)(this.TEXTAREA, pos, pos === endPos ? void 0 : endPos);
};

AutocompleteEditor.prototype.flipDropdownIfNeeded = function () {
  var textareaOffset = (0, _element.offset)(this.TEXTAREA);
  var textareaHeight = (0, _element.outerHeight)(this.TEXTAREA);
  var dropdownHeight = this.getDropdownHeight();
  var trimmingContainer = (0, _element.getTrimmingContainer)(this.instance.view.wt.wtTable.TABLE);
  var trimmingContainerScrollTop = trimmingContainer.scrollTop;
  var headersHeight = (0, _element.outerHeight)(this.instance.view.wt.wtTable.THEAD);
  var containerOffset = {
    row: 0,
    col: 0
  };

  if (trimmingContainer !== window) {
    containerOffset = (0, _element.offset)(trimmingContainer);
  }

  var spaceAbove = textareaOffset.top - containerOffset.top - headersHeight + trimmingContainerScrollTop;
  var spaceBelow = trimmingContainer.scrollHeight - spaceAbove - headersHeight - textareaHeight;
  var flipNeeded = dropdownHeight > spaceBelow && spaceAbove > spaceBelow;

  if (flipNeeded) {
    this.flipDropdown(dropdownHeight);
  } else {
    this.unflipDropdown();
  }

  this.limitDropdownIfNeeded(flipNeeded ? spaceAbove : spaceBelow, dropdownHeight);

  return flipNeeded;
};

AutocompleteEditor.prototype.limitDropdownIfNeeded = function (spaceAvailable, dropdownHeight) {
  if (dropdownHeight > spaceAvailable) {
    var tempHeight = 0;
    var i = 0;
    var lastRowHeight = 0;
    var height = null;

    do {
      lastRowHeight = this.htEditor.getRowHeight(i) || this.htEditor.view.wt.wtSettings.settings.defaultRowHeight;
      tempHeight += lastRowHeight;
      i++;
    } while (tempHeight < spaceAvailable);

    height = tempHeight - lastRowHeight;

    if (this.htEditor.flipped) {
      this.htEditor.rootElement.style.top = parseInt(this.htEditor.rootElement.style.top, 10) + dropdownHeight - height + 'px';
    }

    this.setDropdownHeight(tempHeight - lastRowHeight);
  }
};

AutocompleteEditor.prototype.flipDropdown = function (dropdownHeight) {
  var dropdownStyle = this.htEditor.rootElement.style;

  dropdownStyle.position = 'absolute';
  dropdownStyle.top = -dropdownHeight + 'px';

  this.htEditor.flipped = true;
};

AutocompleteEditor.prototype.unflipDropdown = function () {
  var dropdownStyle = this.htEditor.rootElement.style;

  if (dropdownStyle.position === 'absolute') {
    dropdownStyle.position = '';
    dropdownStyle.top = '';
  }

  this.htEditor.flipped = void 0;
};

AutocompleteEditor.prototype.updateDropdownHeight = function () {
  var currentDropdownWidth = this.htEditor.getColWidth(0) + (0, _element.getScrollbarWidth)() + 2;
  var trimDropdown = this.cellProperties.trimDropdown;

  this.htEditor.updateSettings({
    height: this.getDropdownHeight(),
    width: trimDropdown ? void 0 : currentDropdownWidth
  });

  this.htEditor.view.wt.wtTable.alignOverlaysWithTrimmingContainer();
};

AutocompleteEditor.prototype.setDropdownHeight = function (height) {
  this.htEditor.updateSettings({
    height: height
  });
};

AutocompleteEditor.prototype.finishEditing = function (restoreOriginalValue) {
  if (!restoreOriginalValue) {
    this.instance.removeHook('beforeKeyDown', onBeforeKeyDown);
  }
  _handsontableEditor2.default.prototype.finishEditing.apply(this, arguments);
};

AutocompleteEditor.prototype.highlightBestMatchingChoice = function (index) {
  if (typeof index === 'number') {
    this.htEditor.selectCell(index, 0);
  } else {
    this.htEditor.deselectCell();
  }
};

/**
 * Filters and sorts by relevance
 * @param value
 * @param choices
 * @param caseSensitive
 * @returns {Array} array of indexes in original choices array
 */
AutocompleteEditor.sortByRelevance = function (value, choices, caseSensitive) {
  var choicesRelevance = [];
  var currentItem = void 0;
  var valueLength = value.length;
  var valueIndex = void 0;
  var charsLeft = void 0;
  var result = [];
  var i = void 0;
  var choicesCount = choices.length;

  if (valueLength === 0) {
    for (i = 0; i < choicesCount; i++) {
      result.push(i);
    }
    return result;
  }

  for (i = 0; i < choicesCount; i++) {
    currentItem = (0, _string.stripTags)((0, _mixed.stringify)(choices[i]));

    if (caseSensitive) {
      valueIndex = currentItem.indexOf(value);
    } else {
      valueIndex = currentItem.toLowerCase().indexOf(value.toLowerCase());
    }

    if (valueIndex !== -1) {
      charsLeft = currentItem.length - valueIndex - valueLength;

      choicesRelevance.push({
        baseIndex: i,
        index: valueIndex,
        charsLeft: charsLeft,
        value: currentItem
      });
    }
  }

  choicesRelevance.sort(function (a, b) {

    if (b.index === -1) {
      return -1;
    }
    if (a.index === -1) {
      return 1;
    }

    if (a.index < b.index) {
      return -1;
    } else if (b.index < a.index) {
      return 1;
    } else if (a.index === b.index) {
      if (a.charsLeft < b.charsLeft) {
        return -1;
      } else if (a.charsLeft > b.charsLeft) {
        return 1;
      }
    }

    return 0;
  });

  for (i = 0, choicesCount = choicesRelevance.length; i < choicesCount; i++) {
    result.push(choicesRelevance[i].baseIndex);
  }

  return result;
};

AutocompleteEditor.prototype.getDropdownHeight = function () {
  var firstRowHeight = this.htEditor.getInstance().getRowHeight(0) || 23;
  var visibleRows = this.cellProperties.visibleRows;

  return this.strippedChoices.length >= visibleRows ? visibleRows * firstRowHeight : this.strippedChoices.length * firstRowHeight + 8;
};

AutocompleteEditor.prototype.stripValueIfNeeded = function (value) {
  return this.stripValuesIfNeeded([value])[0];
};

AutocompleteEditor.prototype.stripValuesIfNeeded = function (values) {
  var allowHtml = this.cellProperties.allowHtml;


  var stringifiedValues = (0, _array.arrayMap)(values, function (value) {
    return (0, _mixed.stringify)(value);
  });
  var strippedValues = (0, _array.arrayMap)(stringifiedValues, function (value) {
    return allowHtml ? value : (0, _string.stripTags)(value);
  });

  return strippedValues;
};

AutocompleteEditor.prototype.allowKeyEventPropagation = function (keyCode) {
  var selected = { row: this.htEditor.getSelectedRange() ? this.htEditor.getSelectedRange().from.row : -1 };
  var allowed = false;

  if (keyCode === _unicode.KEY_CODES.ARROW_DOWN && selected.row > 0 && selected.row < this.htEditor.countRows() - 1) {
    allowed = true;
  }
  if (keyCode === _unicode.KEY_CODES.ARROW_UP && selected.row > -1) {
    allowed = true;
  }

  return allowed;
};

AutocompleteEditor.prototype.discardEditor = function (result) {
  _handsontableEditor2.default.prototype.discardEditor.apply(this, arguments);

  this.instance.view.render();
};

exports.default = AutocompleteEditor;

/***/ }),
/* 264 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


exports.__esModule = true;

var _unicode = __webpack_require__(15);

var _object = __webpack_require__(3);

var _element = __webpack_require__(0);

var _event = __webpack_require__(7);

var _textEditor = __webpack_require__(44);

var _textEditor2 = _interopRequireDefault(_textEditor);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

var HandsontableEditor = _textEditor2.default.prototype.extend();

/**
 * @private
 * @editor HandsontableEditor
 * @class HandsontableEditor
 * @dependencies TextEditor
 */
HandsontableEditor.prototype.createElements = function () {
  _textEditor2.default.prototype.createElements.apply(this, arguments);

  var DIV = document.createElement('DIV');
  DIV.className = 'handsontableEditor';
  this.TEXTAREA_PARENT.appendChild(DIV);

  this.htContainer = DIV;
  this.assignHooks();
};

HandsontableEditor.prototype.prepare = function (td, row, col, prop, value, cellProperties) {
  _textEditor2.default.prototype.prepare.apply(this, arguments);

  var parent = this;
  var options = {
    startRows: 0,
    startCols: 0,
    minRows: 0,
    minCols: 0,
    className: 'listbox',
    copyPaste: false,
    autoColumnSize: false,
    autoRowSize: false,
    readOnly: true,
    fillHandle: false,
    afterOnCellMouseDown: function afterOnCellMouseDown(_, coords) {
      var value = this.getSourceData(coords.row, coords.col);

      // if the value is undefined then it means we don't want to set the value
      if (value !== void 0) {
        parent.setValue(value);
      }
      parent.instance.destroyEditor();
    }
  };

  if (this.cellProperties.handsontable) {
    (0, _object.extend)(options, cellProperties.handsontable);
  }
  this.htOptions = options;
};

var onBeforeKeyDown = function onBeforeKeyDown(event) {
  if ((0, _event.isImmediatePropagationStopped)(event)) {
    return;
  }
  var editor = this.getActiveEditor();

  var innerHOT = editor.htEditor.getInstance();

  var rowToSelect;
  var selectedRow;

  if (event.keyCode == _unicode.KEY_CODES.ARROW_DOWN) {
    if (!innerHOT.getSelected() && !innerHOT.flipped) {
      rowToSelect = 0;
    } else if (innerHOT.getSelected()) {
      if (innerHOT.flipped) {
        rowToSelect = innerHOT.getSelected()[0] + 1;
      } else if (!innerHOT.flipped) {
        selectedRow = innerHOT.getSelected()[0];
        var lastRow = innerHOT.countRows() - 1;
        rowToSelect = Math.min(lastRow, selectedRow + 1);
      }
    }
  } else if (event.keyCode == _unicode.KEY_CODES.ARROW_UP) {
    if (!innerHOT.getSelected() && innerHOT.flipped) {
      rowToSelect = innerHOT.countRows() - 1;
    } else if (innerHOT.getSelected()) {
      if (innerHOT.flipped) {
        selectedRow = innerHOT.getSelected()[0];
        rowToSelect = Math.max(0, selectedRow - 1);
      } else {
        selectedRow = innerHOT.getSelected()[0];
        rowToSelect = selectedRow - 1;
      }
    }
  }

  if (rowToSelect !== void 0) {
    if (rowToSelect < 0 || innerHOT.flipped && rowToSelect > innerHOT.countRows() - 1) {
      innerHOT.deselectCell();
    } else {
      innerHOT.selectCell(rowToSelect, 0);
    }
    if (innerHOT.getData().length) {
      event.preventDefault();
      (0, _event.stopImmediatePropagation)(event);

      editor.instance.listen();
      editor.TEXTAREA.focus();
    }
  }
};

HandsontableEditor.prototype.open = function () {
  this.instance.addHook('beforeKeyDown', onBeforeKeyDown);

  _textEditor2.default.prototype.open.apply(this, arguments);

  if (this.htEditor) {
    this.htEditor.destroy();
  }
  // Construct and initialise a new Handsontable
  this.htEditor = new this.instance.constructor(this.htContainer, this.htOptions);
  this.htEditor.init();

  if (this.cellProperties.strict) {
    this.htEditor.selectCell(0, 0);
    this.TEXTAREA.style.visibility = 'hidden';
  } else {
    this.htEditor.deselectCell();
    this.TEXTAREA.style.visibility = 'visible';
  }

  (0, _element.setCaretPosition)(this.TEXTAREA, 0, this.TEXTAREA.value.length);
};

HandsontableEditor.prototype.close = function () {
  this.instance.removeHook('beforeKeyDown', onBeforeKeyDown);
  this.instance.listen();

  _textEditor2.default.prototype.close.apply(this, arguments);
};

HandsontableEditor.prototype.focus = function () {
  this.instance.listen();
  _textEditor2.default.prototype.focus.apply(this, arguments);
};

HandsontableEditor.prototype.beginEditing = function (initialValue) {
  var onBeginEditing = this.instance.getSettings().onBeginEditing;

  if (onBeginEditing && onBeginEditing() === false) {
    return;
  }
  _textEditor2.default.prototype.beginEditing.apply(this, arguments);
};

HandsontableEditor.prototype.finishEditing = function (isCancelled, ctrlDown) {
  if (this.htEditor && this.htEditor.isListening()) {
    // if focus is still in the HOT editor

    this.instance.listen(); // return the focus to the parent HOT instance
  }

  if (this.htEditor && this.htEditor.getSelected()) {
    var value = this.htEditor.getInstance().getValue();

    if (value !== void 0) {
      // if the value is undefined then it means we don't want to set the value
      this.setValue(value);
    }
  }

  return _textEditor2.default.prototype.finishEditing.apply(this, arguments);
};

HandsontableEditor.prototype.assignHooks = function () {
  var _this = this;

  this.instance.addHook('afterDestroy', function () {
    if (_this.htEditor) {
      _this.htEditor.destroy();
    }
  });
};

exports.default = HandsontableEditor;

/***/ }),
/* 265 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


exports.__esModule = true;

var _array = __webpack_require__(2);

var _object = __webpack_require__(3);

var _number = __webpack_require__(5);

var MIXIN_NAME = 'arrayMapper';

/**
 * @type {Object}
 */
var arrayMapper = {
  _arrayMap: [],

  /**
   * Get value by map index.
   *
   * @param {Number} index Array index.
   * @return {*} Returns value mapped to passed index.
   */
  getValueByIndex: function getValueByIndex(index) {
    var value = void 0;

    // eslint-disable-next-line no-cond-assign, no-return-assign
    return (value = this._arrayMap[index]) === void 0 ? null : value;
  },


  /**
   * Get map index by its value.
   *
   * @param {*} value Value to search.
   * @returns {Number} Returns array index.
   */
  getIndexByValue: function getIndexByValue(value) {
    var index = void 0;

    // eslint-disable-next-line no-cond-assign, no-return-assign
    return (index = this._arrayMap.indexOf(value)) === -1 ? null : index;
  },


  /**
   * Insert new items to array mapper starting at passed index. New entries will be a continuation of last value in the array.
   *
   * @param {Number} index Array index.
   * @param {Number} [amount=1] Defines how many items will be created to an array.
   * @returns {Array} Returns added items.
   */
  insertItems: function insertItems(index) {
    var _this = this;

    var amount = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1;

    var newIndex = (0, _array.arrayMax)(this._arrayMap) + 1;
    var addedItems = [];

    (0, _number.rangeEach)(amount - 1, function (count) {
      addedItems.push(_this._arrayMap.splice(index + count, 0, newIndex + count));
    });

    return addedItems;
  },


  /**
   * Remove items from array mapper.
   *
   * @param {Number} index Array index.
   * @param {Number} [amount=1] Defines how many items will be created to an array.
   * @returns {Array} Returns removed items.
   */
  removeItems: function removeItems(index) {
    var _this2 = this;

    var amount = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1;

    var removedItems = [];

    if (Array.isArray(index)) {
      var mapCopy = [].concat(this._arrayMap);

      // Sort descending
      index.sort(function (a, b) {
        return b - a;
      });

      removedItems = (0, _array.arrayReduce)(index, function (acc, item) {
        _this2._arrayMap.splice(item, 1);

        return acc.concat(mapCopy.slice(item, item + 1));
      }, []);
    } else {
      removedItems = this._arrayMap.splice(index, amount);
    }

    return removedItems;
  },


  /**
   * Unshift items (remove and shift chunk of array to the left).
   *
   * @param {Number|Array} index Array index or Array of indexes to unshift.
   * @param {Number} [amount=1] Defines how many items will be removed from an array (when index is passed as number).
   */
  unshiftItems: function unshiftItems(index) {
    var amount = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1;

    var removedItems = this.removeItems(index, amount);

    function countRowShift(logicalRow) {
      // Todo: compare perf between reduce vs sort->each->brake
      return (0, _array.arrayReduce)(removedItems, function (count, removedLogicalRow) {
        if (logicalRow > removedLogicalRow) {
          count++;
        }

        return count;
      }, 0);
    }

    this._arrayMap = (0, _array.arrayMap)(this._arrayMap, function (logicalRow, physicalRow) {
      var rowShift = countRowShift(logicalRow);

      if (rowShift) {
        logicalRow -= rowShift;
      }

      return logicalRow;
    });
  },


  /**
   * Shift (right shifting) items starting at passed index.
   *
   * @param {Number} index Array index.
   * @param {Number} [amount=1] Defines how many items will be created to an array.
   */
  shiftItems: function shiftItems(index) {
    var _this3 = this;

    var amount = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1;

    this._arrayMap = (0, _array.arrayMap)(this._arrayMap, function (row) {
      if (row >= index) {
        row += amount;
      }

      return row;
    });

    (0, _number.rangeEach)(amount - 1, function (count) {
      _this3._arrayMap.splice(index + count, 0, index + count);
    });
  },


  /**
   * Clear all stored index<->value information from an array.
   */
  clearMap: function clearMap() {
    this._arrayMap.length = 0;
  }
};

(0, _object.defineGetter)(arrayMapper, 'MIXIN_NAME', MIXIN_NAME, {
  writable: false,
  enumerable: false
});

exports.default = arrayMapper;

/***/ }),
/* 266 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


exports.__esModule = true;

var _createClass = 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); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

var _number = __webpack_require__(5);

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

var STATE_INITIALIZED = 0;
var STATE_BUILT = 1;
var STATE_APPENDED = 2;
var UNIT = 'px';

/**
 * @class
 * @private
 */

var BaseUI = function () {
  function BaseUI(hotInstance) {
    _classCallCheck(this, BaseUI);

    /**
     * Instance of Handsontable.
     *
     * @type {Core}
     */
    this.hot = hotInstance;
    /**
     * DOM element representing the ui element.
     *
     * @type {HTMLElement}
     * @private
     */
    this._element = null;
    /**
     * Flag which determines build state of element.
     *
     * @type {Boolean}
     */
    this.state = STATE_INITIALIZED;
  }

  /**
   * Add created UI elements to table.
   *
   * @param {HTMLElement} wrapper Element which are parent for our UI element.
   */


  _createClass(BaseUI, [{
    key: 'appendTo',
    value: function appendTo(wrapper) {
      wrapper.appendChild(this._element);

      this.state = STATE_APPENDED;
    }

    /**
     * Method for create UI element. Only create, without append to table.
     */

  }, {
    key: 'build',
    value: function build() {
      this._element = document.createElement('div');
      this.state = STATE_BUILT;
    }

    /**
     * Method for remove UI element.
     */

  }, {
    key: 'destroy',
    value: function destroy() {
      if (this.isAppended()) {
        this._element.parentElement.removeChild(this._element);
      }

      this._element = null;
      this.state = STATE_INITIALIZED;
    }

    /**
     * Check if UI element are appended.
     *
     * @returns {Boolean}
     */

  }, {
    key: 'isAppended',
    value: function isAppended() {
      return this.state === STATE_APPENDED;
    }

    /**
     * Check if UI element are built.
     *
     * @returns {Boolean}
     */

  }, {
    key: 'isBuilt',
    value: function isBuilt() {
      return this.state >= STATE_BUILT;
    }

    /**
     * Setter for position.
     *
     * @param {Number} top New top position of the element.
     * @param {Number} left New left position of the element.
     */

  }, {
    key: 'setPosition',
    value: function setPosition(top, left) {
      if ((0, _number.isNumeric)(top)) {
        this._element.style.top = top + UNIT;
      }
      if ((0, _number.isNumeric)(left)) {
        this._element.style.left = left + UNIT;
      }
    }

    /**
     * Getter for the element position.
     *
     * @returns {Object} Object contains left and top position of the element.
     */

  }, {
    key: 'getPosition',
    value: function getPosition() {
      return {
        top: this._element.style.top ? parseInt(this._element.style.top, 10) : 0,
        left: this._element.style.left ? parseInt(this._element.style.left, 10) : 0
      };
    }

    /**
     * Setter for the element size.
     *
     * @param {Number} width New width of the element.
     * @param {Number} height New height of the element.
     */

  }, {
    key: 'setSize',
    value: function setSize(width, height) {
      if ((0, _number.isNumeric)(width)) {
        this._element.style.width = width + UNIT;
      }
      if ((0, _number.isNumeric)(height)) {
        this._element.style.height = height + UNIT;
      }
    }

    /**
     * Getter for the element position.
     *
     * @returns {Object} Object contains height and width of the element.
     */

  }, {
    key: 'getSize',
    value: function getSize() {
      return {
        width: this._element.style.width ? parseInt(this._element.style.width, 10) : 0,
        height: this._element.style.height ? parseInt(this._element.style.height, 10) : 0
      };
    }

    /**
     * Setter for the element offset. Offset means marginTop and marginLeft of the element.
     *
     * @param {Number} top New margin top of the element.
     * @param {Number} left New margin left of the element.
     */

  }, {
    key: 'setOffset',
    value: function setOffset(top, left) {
      if ((0, _number.isNumeric)(top)) {
        this._element.style.marginTop = top + UNIT;
      }
      if ((0, _number.isNumeric)(left)) {
        this._element.style.marginLeft = left + UNIT;
      }
    }

    /**
     * Getter for the element offset.
     *
     * @returns {Object} Object contains top and left offset of the element.
     */

  }, {
    key: 'getOffset',
    value: function getOffset() {
      return {
        top: this._element.style.marginTop ? parseInt(this._element.style.marginTop, 10) : 0,
        left: this._element.style.marginLeft ? parseInt(this._element.style.marginLeft, 10) : 0
      };
    }
  }]);

  return BaseUI;
}();

exports.default = BaseUI;

/***/ }),
/* 267 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


exports.__esModule = true;

var _createClass = 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); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

var STATE_INITIALIZED = 0;
var STATE_BUILT = 1;
var STATE_APPENDED = 2;
var UNIT = 'px';

/**
 * @class
 * @private
 */

var BaseUI = function () {
  function BaseUI(hotInstance) {
    _classCallCheck(this, BaseUI);

    /**
     * Instance of Handsontable.
     *
     * @type {Core}
     */
    this.hot = hotInstance;
    /**
     * DOM element representing the ui element.
     *
     * @type {HTMLElement}
     * @private
     */
    this._element = null;
    /**
     * Flag which determines build state of element.
     *
     * @type {Boolean}
     */
    this.state = STATE_INITIALIZED;
  }

  /**
   * Add created UI elements to table.
   *
   * @param {HTMLElement} wrapper Element which are parent for our UI element.
   */


  _createClass(BaseUI, [{
    key: 'appendTo',
    value: function appendTo(wrapper) {
      wrapper.appendChild(this._element);

      this.state = STATE_APPENDED;
    }

    /**
     * Method for create UI element. Only create, without append to table.
     */

  }, {
    key: 'build',
    value: function build() {
      this._element = document.createElement('div');
      this.state = STATE_BUILT;
    }

    /**
     * Method for remove UI element.
     */

  }, {
    key: 'destroy',
    value: function destroy() {
      if (this.isAppended()) {
        this._element.parentElement.removeChild(this._element);
      }

      this._element = null;
      this.state = STATE_INITIALIZED;
    }

    /**
     * Check if UI element are appended.
     *
     * @returns {Boolean}
     */

  }, {
    key: 'isAppended',
    value: function isAppended() {
      return this.state === STATE_APPENDED;
    }

    /**
     * Check if UI element are built.
     *
     * @returns {Boolean}
     */

  }, {
    key: 'isBuilt',
    value: function isBuilt() {
      return this.state >= STATE_BUILT;
    }

    /**
     * Setter for position.
     *
     * @param {Number} top New top position of the element.
     * @param {Number} left New left position of the element.
     */

  }, {
    key: 'setPosition',
    value: function setPosition(top, left) {
      if (top) {
        this._element.style.top = top + UNIT;
      }
      if (left) {
        this._element.style.left = left + UNIT;
      }
    }

    /**
     * Getter for the element position.
     *
     * @returns {Object} Object contains left and top position of the element.
     */

  }, {
    key: 'getPosition',
    value: function getPosition() {
      return {
        top: this._element.style.top ? parseInt(this._element.style.top, 10) : 0,
        left: this._element.style.left ? parseInt(this._element.style.left, 10) : 0
      };
    }

    /**
     * Setter for the element size.
     *
     * @param {Number} width New width of the element.
     * @param {Number} height New height of the element.
     */

  }, {
    key: 'setSize',
    value: function setSize(width, height) {
      if (width) {
        this._element.style.width = width + UNIT;
      }
      if (height) {
        this._element.style.height = height + UNIT;
      }
    }

    /**
     * Getter for the element position.
     *
     * @returns {Object} Object contains height and width of the element.
     */

  }, {
    key: 'getSize',
    value: function getSize() {
      return {
        width: this._element.style.width ? parseInt(this._element.style.width, 10) : 0,
        height: this._element.style.height ? parseInt(this._element.style.height, 10) : 0
      };
    }

    /**
     * Setter for the element offset. Offset means marginTop and marginLeft of the element.
     *
     * @param {Number} top New margin top of the element.
     * @param {Number} left New margin left of the element.
     */

  }, {
    key: 'setOffset',
    value: function setOffset(top, left) {
      if (top) {
        this._element.style.marginTop = top + UNIT;
      }
      if (left) {
        this._element.style.marginLeft = left + UNIT;
      }
    }

    /**
     * Getter for the element offset.
     *
     * @returns {Object} Object contains top and left offset of the element.
     */

  }, {
    key: 'getOffset',
    value: function getOffset() {
      return {
        top: this._element.style.marginTop ? parseInt(this._element.style.marginTop, 10) : 0,
        left: this._element.style.marginLeft ? parseInt(this._element.style.marginLeft, 10) : 0
      };
    }
  }]);

  return BaseUI;
}();

exports.default = BaseUI;

/***/ }),
/* 268 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


exports.__esModule = true;
exports.RecordTranslator = undefined;

var _createClass = 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); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

exports.registerIdentity = registerIdentity;
exports.getTranslator = getTranslator;

var _core = __webpack_require__(66);

var _core2 = _interopRequireDefault(_core);

var _object = __webpack_require__(3);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

/**
 * @class RecordTranslator
 * @util
 */
var RecordTranslator = function () {
  function RecordTranslator(hot) {
    _classCallCheck(this, RecordTranslator);

    this.hot = hot;
  }

  /**
   * Translate physical row index into visual.
   *
   * @param {Number} row Physical row index.
   * @returns {Number} Returns visual row index.
   */


  _createClass(RecordTranslator, [{
    key: 'toVisualRow',
    value: function toVisualRow(row) {
      return this.hot.runHooks('unmodifyRow', row);
    }

    /**
     * Translate physical column index into visual.
     *
     * @param {Number} column Physical column index.
     * @returns {Number} Returns visual column index.
     */

  }, {
    key: 'toVisualColumn',
    value: function toVisualColumn(column) {
      return this.hot.runHooks('unmodifyCol', column);
    }

    /**
     * Translate physical coordinates into visual. Can be passed as separate 2 arguments (row, column) or as an object in first
     * argument with `row` and `column` keys.
     *
     * @param {Number|Object} row Physical coordinates or row index.
     * @param {Number} [column] Physical column index.
     * @returns {Object|Array} Returns an object with visual records or an array if coordinates passed as separate arguments.
     */

  }, {
    key: 'toVisual',
    value: function toVisual(row, column) {
      var result = void 0;

      if ((0, _object.isObject)(row)) {
        result = {
          row: this.toVisualRow(row.row),
          column: this.toVisualColumn(row.column)
        };
      } else {
        result = [this.toVisualRow(row), this.toVisualColumn(column)];
      }

      return result;
    }

    /**
     * Translate visual row index into physical.
     *
     * @param {Number} row Visual row index.
     * @returns {Number} Returns physical row index.
     */

  }, {
    key: 'toPhysicalRow',
    value: function toPhysicalRow(row) {
      return this.hot.runHooks('modifyRow', row);
    }

    /**
     * Translate visual column index into physical.
     *
     * @param {Number} column Visual column index.
     * @returns {Number} Returns physical column index.
     */

  }, {
    key: 'toPhysicalColumn',
    value: function toPhysicalColumn(column) {
      return this.hot.runHooks('modifyCol', column);
    }

    /**
     * Translate visual coordinates into physical. Can be passed as separate 2 arguments (row, column) or as an object in first
     * argument with `row` and `column` keys.
     *
     * @param {Number|Object} row Visual coordinates or row index.
     * @param {Number} [column] Visual column index.
     * @returns {Object|Array} Returns an object with physical records or an array if coordinates passed as separate arguments.
     */

  }, {
    key: 'toPhysical',
    value: function toPhysical(row, column) {
      var result = void 0;

      if ((0, _object.isObject)(row)) {
        result = {
          row: this.toPhysicalRow(row.row),
          column: this.toPhysicalColumn(row.column)
        };
      } else {
        result = [this.toPhysicalRow(row), this.toPhysicalColumn(column)];
      }

      return result;
    }
  }]);

  return RecordTranslator;
}();

exports.RecordTranslator = RecordTranslator;


var identities = new WeakMap();
var translatorSingletons = new WeakMap();

function registerIdentity(identity, hot) {
  identities.set(identity, hot);
}

function getTranslator(identity) {
  var singleton = void 0;

  if (!(identity instanceof _core2.default)) {
    if (!identities.has(identity)) {
      throw Error('Record translator was not registered for this object identity');
    }
    identity = identities.get(identity);
  }
  if (translatorSingletons.has(identity)) {
    singleton = translatorSingletons.get(identity);
  } else {
    singleton = new RecordTranslator(identity);
    translatorSingletons.set(identity, singleton);
  }

  return singleton;
}

/***/ }),
/* 269 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


exports.__esModule = true;

var _createClass = 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); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

var _object = __webpack_require__(3);

var _number = __webpack_require__(5);

var _mixed = __webpack_require__(23);

function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

/**
 * @class SamplesGenerator
 * @util
 */
var SamplesGenerator = function () {
  _createClass(SamplesGenerator, null, [{
    key: 'SAMPLE_COUNT',

    /**
     * Number of samples to take of each value length.
     *
     * @type {Number}
     */
    get: function get() {
      return 3;
    }
  }]);

  function SamplesGenerator(dataFactory) {
    _classCallCheck(this, SamplesGenerator);

    /**
     * Samples prepared for calculations.
     *
     * @type {Map}
     * @default {null}
     */
    this.samples = null;
    /**
     * Function which give the data to collect samples.
     *
     * @type {Function}
     */
    this.dataFactory = dataFactory;
    /**
     * Custom number of samples to take of each value length.
     *
     * @type {Number}
     * @default {null}
     */
    this.customSampleCount = null;
    /**
     * `true` if duplicate samples collection should be allowed, `false` otherwise.
     *
     * @type {Boolean}
     * @default {false}
     */
    this.allowDuplicates = false;
  }

  /**
   * Get the sample count for this instance.
   *
   * @returns {Number}
   */


  _createClass(SamplesGenerator, [{
    key: 'getSampleCount',
    value: function getSampleCount() {
      if (this.customSampleCount) {
        return this.customSampleCount;
      }
      return SamplesGenerator.SAMPLE_COUNT;
    }
  }, {
    key: 'setSampleCount',


    /**
     * Set the sample count.
     *
     * @param {Number} sampleCount Number of samples to be collected.
     */
    value: function setSampleCount(sampleCount) {
      this.customSampleCount = sampleCount;
    }

    /**
     * Set if the generator should accept duplicate values.
     *
     * @param {Boolean} allowDuplicates `true` to allow duplicate values.
     */

  }, {
    key: 'setAllowDuplicates',
    value: function setAllowDuplicates(allowDuplicates) {
      this.allowDuplicates = allowDuplicates;
    }

    /**
     * Generate samples for row. You can control which area should be sampled by passing `rowRange` object and `colRange` object.
     *
     * @param {Object|Number} rowRange
     * @param {Object} colRange
     * @returns {Object}
     */

  }, {
    key: 'generateRowSamples',
    value: function generateRowSamples(rowRange, colRange) {
      return this.generateSamples('row', colRange, rowRange);
    }

    /**
     * Generate samples for column. You can control which area should be sampled by passing `colRange` object and `rowRange` object.
     *
     * @param {Object} colRange Column index.
     * @param {Object} rowRange Column index.
     * @returns {Object}
     */

  }, {
    key: 'generateColumnSamples',
    value: function generateColumnSamples(colRange, rowRange) {
      return this.generateSamples('col', rowRange, colRange);
    }

    /**
     * Generate collection of samples.
     *
     * @param {String} type Type to generate. Can be `col` or `row`.
     * @param {Object} range
     * @param {Object|Number} specifierRange
     * @returns {Map}
     */

  }, {
    key: 'generateSamples',
    value: function generateSamples(type, range, specifierRange) {
      var _this = this;

      var samples = new Map();

      if (typeof specifierRange === 'number') {
        specifierRange = { from: specifierRange, to: specifierRange };
      }
      (0, _number.rangeEach)(specifierRange.from, specifierRange.to, function (index) {
        var sample = _this.generateSample(type, range, index);

        samples.set(index, sample);
      });

      return samples;
    }

    /**
     * Generate sample for specified type (`row` or `col`).
     *
     * @param {String} type Samples type `row` or `col`.
     * @param {Object} range
     * @param {Number} specifierValue
     * @returns {Map}
     */

  }, {
    key: 'generateSample',
    value: function generateSample(type, range, specifierValue) {
      var _this2 = this;

      var samples = new Map();
      var sampledValues = [];
      var length = void 0;

      (0, _number.rangeEach)(range.from, range.to, function (index) {
        var value = void 0;

        if (type === 'row') {
          value = _this2.dataFactory(specifierValue, index);
        } else if (type === 'col') {
          value = _this2.dataFactory(index, specifierValue);
        } else {
          throw new Error('Unsupported sample type');
        }

        if ((0, _object.isObject)(value)) {
          length = Object.keys(value).length;
        } else if (Array.isArray(value)) {
          length = value.length;
        } else {
          length = (0, _mixed.stringify)(value).length;
        }

        if (!samples.has(length)) {
          samples.set(length, {
            needed: _this2.getSampleCount(),
            strings: []
          });
        }
        var sample = samples.get(length);

        if (sample.needed) {
          var duplicate = sampledValues.indexOf(value) > -1;

          if (!duplicate || _this2.allowDuplicates) {
            var computedKey = type === 'row' ? 'col' : 'row';

            sample.strings.push(_defineProperty({ value: value }, computedKey, index));
            sampledValues.push(value);
            sample.needed--;
          }
        }
      });

      return samples;
    }
  }]);

  return SamplesGenerator;
}();

exports.default = SamplesGenerator;

/***/ }),
/* 270 */
/***/ (function(module, exports, __webpack_require__) {

// false -> Array#indexOf
// true  -> Array#includes
var toIObject = __webpack_require__(27);
var toLength = __webpack_require__(21);
var toAbsoluteIndex = __webpack_require__(63);
module.exports = function (IS_INCLUDES) {
  return function ($this, el, fromIndex) {
    var O = toIObject($this);
    var length = toLength(O.length);
    var index = toAbsoluteIndex(fromIndex, length);
    var value;
    // Array#includes uses SameValueZero equality algorithm
    // eslint-disable-next-line no-self-compare
    if (IS_INCLUDES && el != el) while (length > index) {
      value = O[index++];
      // eslint-disable-next-line no-self-compare
      if (value != value) return true;
    // Array#indexOf ignores holes, Array#includes - not
    } else for (;length > index; index++) if (IS_INCLUDES || index in O) {
      if (O[index] === el) return IS_INCLUDES || index || 0;
    } return !IS_INCLUDES && -1;
  };
};


/***/ }),
/* 271 */
/***/ (function(module, exports, __webpack_require__) {

// getting tag from 19.1.3.6 Object.prototype.toString()
var cof = __webpack_require__(38);
var TAG = __webpack_require__(8)('toStringTag');
// ES3 wrong here
var ARG = cof(function () { return arguments; }()) == 'Arguments';

// fallback for IE11 Script Access Denied error
var tryGet = function (it, key) {
  try {
    return it[key];
  } catch (e) { /* empty */ }
};

module.exports = function (it) {
  var O, T, B;
  return it === undefined ? 'Undefined' : it === null ? 'Null'
    // @@toStringTag case
    : typeof (T = tryGet(O = Object(it), TAG)) == 'string' ? T
    // builtinTag case
    : ARG ? cof(O)
    // ES3 arguments fallback
    : (B = cof(O)) == 'Object' && typeof O.callee == 'function' ? 'Arguments' : B;
};


/***/ }),
/* 272 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";

var dP = __webpack_require__(18).f;
var create = __webpack_require__(80);
var redefineAll = __webpack_require__(62);
var ctx = __webpack_require__(30);
var anInstance = __webpack_require__(55);
var forOf = __webpack_require__(59);
var $iterDefine = __webpack_require__(281);
var step = __webpack_require__(282);
var setSpecies = __webpack_require__(288);
var DESCRIPTORS = __webpack_require__(20);
var fastKey = __webpack_require__(47).fastKey;
var validate = __webpack_require__(41);
var SIZE = DESCRIPTORS ? '_s' : 'size';

var getEntry = function (that, key) {
  // fast case
  var index = fastKey(key);
  var entry;
  if (index !== 'F') return that._i[index];
  // frozen object case
  for (entry = that._f; entry; entry = entry.n) {
    if (entry.k == key) return entry;
  }
};

module.exports = {
  getConstructor: function (wrapper, NAME, IS_MAP, ADDER) {
    var C = wrapper(function (that, iterable) {
      anInstance(that, C, NAME, '_i');
      that._t = NAME;         // collection type
      that._i = create(null); // index
      that._f = undefined;    // first entry
      that._l = undefined;    // last entry
      that[SIZE] = 0;         // size
      if (iterable != undefined) forOf(iterable, IS_MAP, that[ADDER], that);
    });
    redefineAll(C.prototype, {
      // 23.1.3.1 Map.prototype.clear()
      // 23.2.3.2 Set.prototype.clear()
      clear: function clear() {
        for (var that = validate(this, NAME), data = that._i, entry = that._f; entry; entry = entry.n) {
          entry.r = true;
          if (entry.p) entry.p = entry.p.n = undefined;
          delete data[entry.i];
        }
        that._f = that._l = undefined;
        that[SIZE] = 0;
      },
      // 23.1.3.3 Map.prototype.delete(key)
      // 23.2.3.4 Set.prototype.delete(value)
      'delete': function (key) {
        var that = validate(this, NAME);
        var entry = getEntry(that, key);
        if (entry) {
          var next = entry.n;
          var prev = entry.p;
          delete that._i[entry.i];
          entry.r = true;
          if (prev) prev.n = next;
          if (next) next.p = prev;
          if (that._f == entry) that._f = next;
          if (that._l == entry) that._l = prev;
          that[SIZE]--;
        } return !!entry;
      },
      // 23.2.3.6 Set.prototype.forEach(callbackfn, thisArg = undefined)
      // 23.1.3.5 Map.prototype.forEach(callbackfn, thisArg = undefined)
      forEach: function forEach(callbackfn /* , that = undefined */) {
        validate(this, NAME);
        var f = ctx(callbackfn, arguments.length > 1 ? arguments[1] : undefined, 3);
        var entry;
        while (entry = entry ? entry.n : this._f) {
          f(entry.v, entry.k, this);
          // revert to the last existing entry
          while (entry && entry.r) entry = entry.p;
        }
      },
      // 23.1.3.7 Map.prototype.has(key)
      // 23.2.3.7 Set.prototype.has(value)
      has: function has(key) {
        return !!getEntry(validate(this, NAME), key);
      }
    });
    if (DESCRIPTORS) dP(C.prototype, 'size', {
      get: function () {
        return validate(this, NAME)[SIZE];
      }
    });
    return C;
  },
  def: function (that, key, value) {
    var entry = getEntry(that, key);
    var prev, index;
    // change existing entry
    if (entry) {
      entry.v = value;
    // create new entry
    } else {
      that._l = entry = {
        i: index = fastKey(key, true), // <- index
        k: key,                        // <- key
        v: value,                      // <- value
        p: prev = that._l,             // <- previous entry
        n: undefined,                  // <- next entry
        r: false                       // <- removed
      };
      if (!that._f) that._f = entry;
      if (prev) prev.n = entry;
      that[SIZE]++;
      // add to index
      if (index !== 'F') that._i[index] = entry;
    } return that;
  },
  getEntry: getEntry,
  setStrong: function (C, NAME, IS_MAP) {
    // add .keys, .values, .entries, [@@iterator]
    // 23.1.3.4, 23.1.3.8, 23.1.3.11, 23.1.3.12, 23.2.3.5, 23.2.3.8, 23.2.3.10, 23.2.3.11
    $iterDefine(C, NAME, function (iterated, kind) {
      this._t = validate(iterated, NAME); // target
      this._k = kind;                     // kind
      this._l = undefined;                // previous
    }, function () {
      var that = this;
      var kind = that._k;
      var entry = that._l;
      // revert to the last existing entry
      while (entry && entry.r) entry = entry.p;
      // get next entry
      if (!that._t || !(that._l = entry = entry ? entry.n : that._t._f)) {
        // or finish the iteration
        that._t = undefined;
        return step(1);
      }
      // return step by kind
      if (kind == 'keys') return step(0, entry.k);
      if (kind == 'values') return step(0, entry.v);
      return step(0, [entry.k, entry.v]);
    }, IS_MAP ? 'entries' : 'values', !IS_MAP, true);

    // add [@@species], 23.1.2.2, 23.2.2.2
    setSpecies(NAME);
  }
};


/***/ }),
/* 273 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";

var redefineAll = __webpack_require__(62);
var getWeak = __webpack_require__(47).getWeak;
var anObject = __webpack_require__(17);
var isObject = __webpack_require__(12);
var anInstance = __webpack_require__(55);
var forOf = __webpack_require__(59);
var createArrayMethod = __webpack_require__(56);
var $has = __webpack_require__(26);
var validate = __webpack_require__(41);
var arrayFind = createArrayMethod(5);
var arrayFindIndex = createArrayMethod(6);
var id = 0;

// fallback for uncaught frozen keys
var uncaughtFrozenStore = function (that) {
  return that._l || (that._l = new UncaughtFrozenStore());
};
var UncaughtFrozenStore = function () {
  this.a = [];
};
var findUncaughtFrozen = function (store, key) {
  return arrayFind(store.a, function (it) {
    return it[0] === key;
  });
};
UncaughtFrozenStore.prototype = {
  get: function (key) {
    var entry = findUncaughtFrozen(this, key);
    if (entry) return entry[1];
  },
  has: function (key) {
    return !!findUncaughtFrozen(this, key);
  },
  set: function (key, value) {
    var entry = findUncaughtFrozen(this, key);
    if (entry) entry[1] = value;
    else this.a.push([key, value]);
  },
  'delete': function (key) {
    var index = arrayFindIndex(this.a, function (it) {
      return it[0] === key;
    });
    if (~index) this.a.splice(index, 1);
    return !!~index;
  }
};

module.exports = {
  getConstructor: function (wrapper, NAME, IS_MAP, ADDER) {
    var C = wrapper(function (that, iterable) {
      anInstance(that, C, NAME, '_i');
      that._t = NAME;      // collection type
      that._i = id++;      // collection id
      that._l = undefined; // leak store for uncaught frozen objects
      if (iterable != undefined) forOf(iterable, IS_MAP, that[ADDER], that);
    });
    redefineAll(C.prototype, {
      // 23.3.3.2 WeakMap.prototype.delete(key)
      // 23.4.3.3 WeakSet.prototype.delete(value)
      'delete': function (key) {
        if (!isObject(key)) return false;
        var data = getWeak(key);
        if (data === true) return uncaughtFrozenStore(validate(this, NAME))['delete'](key);
        return data && $has(data, this._i) && delete data[this._i];
      },
      // 23.3.3.4 WeakMap.prototype.has(key)
      // 23.4.3.4 WeakSet.prototype.has(value)
      has: function has(key) {
        if (!isObject(key)) return false;
        var data = getWeak(key);
        if (data === true) return uncaughtFrozenStore(validate(this, NAME)).has(key);
        return data && $has(data, this._i);
      }
    });
    return C;
  },
  def: function (that, key, value) {
    var data = getWeak(anObject(key), true);
    if (data === true) uncaughtFrozenStore(that).set(key, value);
    else data[that._i] = value;
    return that;
  },
  ufstore: uncaughtFrozenStore
};


/***/ }),
/* 274 */
/***/ (function(module, exports, __webpack_require__) {

var document = __webpack_require__(10).document;
module.exports = document && document.documentElement;


/***/ }),
/* 275 */
/***/ (function(module, exports, __webpack_require__) {

module.exports = !__webpack_require__(20) && !__webpack_require__(25)(function () {
  return Object.defineProperty(__webpack_require__(75)('div'), 'a', { get: function () { return 7; } }).a != 7;
});


/***/ }),
/* 276 */
/***/ (function(module, exports, __webpack_require__) {

// check on default Array iterator
var Iterators = __webpack_require__(46);
var ITERATOR = __webpack_require__(8)('iterator');
var ArrayProto = Array.prototype;

module.exports = function (it) {
  return it !== undefined && (Iterators.Array === it || ArrayProto[ITERATOR] === it);
};


/***/ }),
/* 277 */
/***/ (function(module, exports, __webpack_require__) {

// 7.2.2 IsArray(argument)
var cof = __webpack_require__(38);
module.exports = Array.isArray || function isArray(arg) {
  return cof(arg) == 'Array';
};


/***/ }),
/* 278 */
/***/ (function(module, exports, __webpack_require__) {

// 20.1.2.3 Number.isInteger(number)
var isObject = __webpack_require__(12);
var floor = Math.floor;
module.exports = function isInteger(it) {
  return !isObject(it) && isFinite(it) && floor(it) === it;
};


/***/ }),
/* 279 */
/***/ (function(module, exports, __webpack_require__) {

// 7.2.8 IsRegExp(argument)
var isObject = __webpack_require__(12);
var cof = __webpack_require__(38);
var MATCH = __webpack_require__(8)('match');
module.exports = function (it) {
  var isRegExp;
  return isObject(it) && ((isRegExp = it[MATCH]) !== undefined ? !!isRegExp : cof(it) == 'RegExp');
};


/***/ }),
/* 280 */
/***/ (function(module, exports, __webpack_require__) {

// call something on iterator step with safe closing on error
var anObject = __webpack_require__(17);
module.exports = function (iterator, fn, value, entries) {
  try {
    return entries ? fn(anObject(value)[0], value[1]) : fn(value);
  // 7.4.6 IteratorClose(iterator, completion)
  } catch (e) {
    var ret = iterator['return'];
    if (ret !== undefined) anObject(ret.call(iterator));
    throw e;
  }
};


/***/ }),
/* 281 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";

var LIBRARY = __webpack_require__(60);
var $export = __webpack_require__(1);
var redefine = __webpack_require__(32);
var hide = __webpack_require__(31);
var has = __webpack_require__(26);
var Iterators = __webpack_require__(46);
var $iterCreate = __webpack_require__(397);
var setToStringTag = __webpack_require__(50);
var getPrototypeOf = __webpack_require__(401);
var ITERATOR = __webpack_require__(8)('iterator');
var BUGGY = !([].keys && 'next' in [].keys()); // Safari has buggy iterators w/o `next`
var FF_ITERATOR = '@@iterator';
var KEYS = 'keys';
var VALUES = 'values';

var returnThis = function () { return this; };

module.exports = function (Base, NAME, Constructor, next, DEFAULT, IS_SET, FORCED) {
  $iterCreate(Constructor, NAME, next);
  var getMethod = function (kind) {
    if (!BUGGY && kind in proto) return proto[kind];
    switch (kind) {
      case KEYS: return function keys() { return new Constructor(this, kind); };
      case VALUES: return function values() { return new Constructor(this, kind); };
    } return function entries() { return new Constructor(this, kind); };
  };
  var TAG = NAME + ' Iterator';
  var DEF_VALUES = DEFAULT == VALUES;
  var VALUES_BUG = false;
  var proto = Base.prototype;
  var $native = proto[ITERATOR] || proto[FF_ITERATOR] || DEFAULT && proto[DEFAULT];
  var $default = $native || getMethod(DEFAULT);
  var $entries = DEFAULT ? !DEF_VALUES ? $default : getMethod('entries') : undefined;
  var $anyNative = NAME == 'Array' ? proto.entries || $native : $native;
  var methods, key, IteratorPrototype;
  // Fix native
  if ($anyNative) {
    IteratorPrototype = getPrototypeOf($anyNative.call(new Base()));
    if (IteratorPrototype !== Object.prototype && IteratorPrototype.next) {
      // Set @@toStringTag to native iterators
      setToStringTag(IteratorPrototype, TAG, true);
      // fix for some old engines
      if (!LIBRARY && !has(IteratorPrototype, ITERATOR)) hide(IteratorPrototype, ITERATOR, returnThis);
    }
  }
  // fix Array#{values, @@iterator}.name in V8 / FF
  if (DEF_VALUES && $native && $native.name !== VALUES) {
    VALUES_BUG = true;
    $default = function values() { return $native.call(this); };
  }
  // Define iterator
  if ((!LIBRARY || FORCED) && (BUGGY || VALUES_BUG || !proto[ITERATOR])) {
    hide(proto, ITERATOR, $default);
  }
  // Plug for library
  Iterators[NAME] = $default;
  Iterators[TAG] = returnThis;
  if (DEFAULT) {
    methods = {
      values: DEF_VALUES ? $default : getMethod(VALUES),
      keys: IS_SET ? $default : getMethod(KEYS),
      entries: $entries
    };
    if (FORCED) for (key in methods) {
      if (!(key in proto)) redefine(proto, key, methods[key]);
    } else $export($export.P + $export.F * (BUGGY || VALUES_BUG), NAME, methods);
  }
  return methods;
};


/***/ }),
/* 282 */
/***/ (function(module, exports) {

module.exports = function (done, value) {
  return { value: value, done: !!done };
};


/***/ }),
/* 283 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";

// 25.4.1.5 NewPromiseCapability(C)
var aFunction = __webpack_require__(54);

function PromiseCapability(C) {
  var resolve, reject;
  this.promise = new C(function ($$resolve, $$reject) {
    if (resolve !== undefined || reject !== undefined) throw TypeError('Bad Promise constructor');
    resolve = $$resolve;
    reject = $$reject;
  });
  this.resolve = aFunction(resolve);
  this.reject = aFunction(reject);
}

module.exports.f = function (C) {
  return new PromiseCapability(C);
};


/***/ }),
/* 284 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";

// 19.1.2.1 Object.assign(target, source, ...)
var getKeys = __webpack_require__(39);
var gOPS = __webpack_require__(61);
var pIE = __webpack_require__(48);
var toObject = __webpack_require__(40);
var IObject = __webpack_require__(78);
var $assign = Object.assign;

// should work with symbols and should have deterministic property order (V8 bug)
module.exports = !$assign || __webpack_require__(25)(function () {
  var A = {};
  var B = {};
  // eslint-disable-next-line no-undef
  var S = Symbol();
  var K = 'abcdefghijklmnopqrst';
  A[S] = 7;
  K.split('').forEach(function (k) { B[k] = k; });
  return $assign({}, A)[S] != 7 || Object.keys($assign({}, B)).join('') != K;
}) ? function assign(target, source) { // eslint-disable-line no-unused-vars
  var T = toObject(target);
  var aLen = arguments.length;
  var index = 1;
  var getSymbols = gOPS.f;
  var isEnum = pIE.f;
  while (aLen > index) {
    var S = IObject(arguments[index++]);
    var keys = getSymbols ? getKeys(S).concat(getSymbols(S)) : getKeys(S);
    var length = keys.length;
    var j = 0;
    var key;
    while (length > j) if (isEnum.call(S, key = keys[j++])) T[key] = S[key];
  } return T;
} : $assign;


/***/ }),
/* 285 */
/***/ (function(module, exports, __webpack_require__) {

var has = __webpack_require__(26);
var toIObject = __webpack_require__(27);
var arrayIndexOf = __webpack_require__(270)(false);
var IE_PROTO = __webpack_require__(83)('IE_PROTO');

module.exports = function (object, names) {
  var O = toIObject(object);
  var i = 0;
  var result = [];
  var key;
  for (key in O) if (key != IE_PROTO) has(O, key) && result.push(key);
  // Don't enum bug & hidden keys
  while (names.length > i) if (has(O, key = names[i++])) {
    ~arrayIndexOf(result, key) || result.push(key);
  }
  return result;
};


/***/ }),
/* 286 */
/***/ (function(module, exports, __webpack_require__) {

var getKeys = __webpack_require__(39);
var toIObject = __webpack_require__(27);
var isEnum = __webpack_require__(48).f;
module.exports = function (isEntries) {
  return function (it) {
    var O = toIObject(it);
    var keys = getKeys(O);
    var length = keys.length;
    var i = 0;
    var result = [];
    var key;
    while (length > i) if (isEnum.call(O, key = keys[i++])) {
      result.push(isEntries ? [key, O[key]] : O[key]);
    } return result;
  };
};


/***/ }),
/* 287 */
/***/ (function(module, exports, __webpack_require__) {

// Works with __proto__ only. Old v8 can't work with null proto objects.
/* eslint-disable no-proto */
var isObject = __webpack_require__(12);
var anObject = __webpack_require__(17);
var check = function (O, proto) {
  anObject(O);
  if (!isObject(proto) && proto !== null) throw TypeError(proto + ": can't set as prototype!");
};
module.exports = {
  set: Object.setPrototypeOf || ('__proto__' in {} ? // eslint-disable-line
    function (test, buggy, set) {
      try {
        set = __webpack_require__(30)(Function.call, __webpack_require__(81).f(Object.prototype, '__proto__').set, 2);
        set(test, []);
        buggy = !(test instanceof Array);
      } catch (e) { buggy = true; }
      return function setPrototypeOf(O, proto) {
        check(O, proto);
        if (buggy) O.__proto__ = proto;
        else set(O, proto);
        return O;
      };
    }({}, false) : undefined),
  check: check
};


/***/ }),
/* 288 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";

var global = __webpack_require__(10);
var dP = __webpack_require__(18);
var DESCRIPTORS = __webpack_require__(20);
var SPECIES = __webpack_require__(8)('species');

module.exports = function (KEY) {
  var C = global[KEY];
  if (DESCRIPTORS && C && !C[SPECIES]) dP.f(C, SPECIES, {
    configurable: true,
    get: function () { return this; }
  });
};


/***/ }),
/* 289 */
/***/ (function(module, exports, __webpack_require__) {

// https://github.com/tc39/proposal-string-pad-start-end
var toLength = __webpack_require__(21);
var repeat = __webpack_require__(290);
var defined = __webpack_require__(33);

module.exports = function (that, maxLength, fillString, left) {
  var S = String(defined(that));
  var stringLength = S.length;
  var fillStr = fillString === undefined ? ' ' : String(fillString);
  var intMaxLength = toLength(maxLength);
  if (intMaxLength <= stringLength || fillStr == '') return S;
  var fillLen = intMaxLength - stringLength;
  var stringFiller = repeat.call(fillStr, Math.ceil(fillLen / fillStr.length));
  if (stringFiller.length > fillLen) stringFiller = stringFiller.slice(0, fillLen);
  return left ? stringFiller + S : S + stringFiller;
};


/***/ }),
/* 290 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";

var toInteger = __webpack_require__(64);
var defined = __webpack_require__(33);

module.exports = function repeat(count) {
  var str = String(defined(this));
  var res = '';
  var n = toInteger(count);
  if (n < 0 || n == Infinity) throw RangeError("Count can't be negative");
  for (;n > 0; (n >>>= 1) && (str += str)) if (n & 1) res += str;
  return res;
};


/***/ }),
/* 291 */
/***/ (function(module, exports, __webpack_require__) {

exports.f = __webpack_require__(8);


/***/ }),
/* 292 */
/***/ (function(module, exports, __webpack_require__) {

var classof = __webpack_require__(271);
var ITERATOR = __webpack_require__(8)('iterator');
var Iterators = __webpack_require__(46);
module.exports = __webpack_require__(45).getIteratorMethod = function (it) {
  if (it != undefined) return it[ITERATOR]
    || it['@@iterator']
    || Iterators[classof(it)];
};


/***/ }),
/* 293 */
/***/ (function(module, exports) {

// removed by extract-text-webpack-plugin

/***/ }),
/* 294 */
/***/ (function(module, exports) {

// removed by extract-text-webpack-plugin

/***/ }),
/* 295 */
/***/ (function(module, exports) {

// removed by extract-text-webpack-plugin

/***/ }),
/* 296 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


exports.__esModule = true;
exports.default = jQueryWrapper;
function jQueryWrapper(Handsontable) {
  var jQuery = typeof window === 'undefined' ? false : window.jQuery;

  if (!jQuery) {
    return;
  }

  jQuery.fn.handsontable = function (action) {
    var $this = this.first(); // Use only first element from list
    var instance = $this.data('handsontable');

    // Init case
    if (typeof action !== 'string') {
      var userSettings = action || {};

      if (instance) {
        instance.updateSettings(userSettings);
      } else {
        instance = new Handsontable.Core($this[0], userSettings);
        $this.data('handsontable', instance);
        instance.init();
      }

      return $this;
    }

    // Action case
    var args = [];
    var output = void 0;

    if (arguments.length > 1) {
      for (var i = 1, ilen = arguments.length; i < ilen; i++) {
        args.push(arguments[i]);
      }
    }

    if (instance) {
      if (typeof instance[action] !== 'undefined') {
        output = instance[action].apply(instance, args);

        if (action === 'destroy') {
          $this.removeData();
        }
      } else {
        throw new Error('Handsontable do not provide action: ' + action);
      }
    }

    return output;
  };
};

/***/ }),
/* 297 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


exports.__esModule = true;
exports.Base = exports.Search = exports.MultipleSelectionHandles = exports.MergeCells = exports.ManualRowResize = exports.ManualRowMove = exports.ManualColumnResize = exports.ManualColumnMove = exports.ManualColumnFreeze = exports.DragToScroll = exports.CopyPaste = exports.ContextMenu = exports.AutoRowSize = exports.AutoFill = exports.AutoColumnSize = undefined;

var _autoColumnSize = __webpack_require__(335);

var _autoColumnSize2 = _interopRequireDefault(_autoColumnSize);

var _autofill = __webpack_require__(337);

var _autofill2 = _interopRequireDefault(_autofill);

var _autoRowSize = __webpack_require__(336);

var _autoRowSize2 = _interopRequireDefault(_autoRowSize);

var _contextMenu = __webpack_require__(340);

var _contextMenu2 = _interopRequireDefault(_contextMenu);

var _copyPaste = __webpack_require__(357);

var _copyPaste2 = _interopRequireDefault(_copyPaste);

var _dragToScroll = __webpack_require__(359);

var _dragToScroll2 = _interopRequireDefault(_dragToScroll);

var _manualColumnFreeze = __webpack_require__(362);

var _manualColumnFreeze2 = _interopRequireDefault(_manualColumnFreeze);

var _manualColumnMove = __webpack_require__(364);

var _manualColumnMove2 = _interopRequireDefault(_manualColumnMove);

var _manualColumnResize = __webpack_require__(367);

var _manualColumnResize2 = _interopRequireDefault(_manualColumnResize);

var _manualRowMove = __webpack_require__(368);

var _manualRowMove2 = _interopRequireDefault(_manualRowMove);

var _manualRowResize = __webpack_require__(372);

var _manualRowResize2 = _interopRequireDefault(_manualRowResize);

var _mergeCells = __webpack_require__(373);

var _mergeCells2 = _interopRequireDefault(_mergeCells);

var _multipleSelectionHandles = __webpack_require__(374);

var _multipleSelectionHandles2 = _interopRequireDefault(_multipleSelectionHandles);

var _search = __webpack_require__(375);

var _search2 = _interopRequireDefault(_search);

var _base = __webpack_require__(16);

var _base2 = _interopRequireDefault(_base);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

exports.AutoColumnSize = _autoColumnSize2.default;
exports.AutoFill = _autofill2.default;
exports.AutoRowSize = _autoRowSize2.default;
exports.ContextMenu = _contextMenu2.default;
exports.CopyPaste = _copyPaste2.default;
exports.DragToScroll = _dragToScroll2.default;
exports.ManualColumnFreeze = _manualColumnFreeze2.default;
exports.ManualColumnMove = _manualColumnMove2.default;
exports.ManualColumnResize = _manualColumnResize2.default;
exports.ManualRowMove = _manualRowMove2.default;
exports.ManualRowResize = _manualRowResize2.default;
exports.MergeCells = _mergeCells2.default;
exports.MultipleSelectionHandles = _multipleSelectionHandles2.default;
exports.Search = _search2.default;
exports.Base = _base2.default;

/***/ }),
/* 298 */
/***/ (function(module, exports) {

// removed by extract-text-webpack-plugin

/***/ }),
/* 299 */
/***/ (function(module, exports) {

// removed by extract-text-webpack-plugin

/***/ }),
/* 300 */
/***/ (function(module, exports) {

// removed by extract-text-webpack-plugin

/***/ }),
/* 301 */
/***/ (function(module, exports) {

// removed by extract-text-webpack-plugin

/***/ }),
/* 302 */
/***/ (function(module, exports) {

// removed by extract-text-webpack-plugin

/***/ }),
/* 303 */
/***/ (function(module, exports) {

// removed by extract-text-webpack-plugin

/***/ }),
/* 304 */
/***/ (function(module, exports) {

module.exports = function(module) {
	if(!module.webpackPolyfill) {
		module.deprecate = function() {};
		module.paths = [];
		// module.parent = undefined by default
		if(!module.children) module.children = [];
		Object.defineProperty(module, "loaded", {
			enumerable: true,
			get: function() {
				return module.l;
			}
		});
		Object.defineProperty(module, "id", {
			enumerable: true,
			get: function() {
				return module.i;
			}
		});
		module.webpackPolyfill = 1;
	}
	return module;
};


/***/ }),
/* 305 */
/***/ (function(module, exports) {



/***/ }),
/* 306 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


/**
 * autoResize - resizes a DOM element to the width and height of another DOM element
 *
 * Copyright 2014, Marcin Warpechowski
 * Licensed under the MIT license
 */

function autoResize() {
  var defaults = {
    minHeight: 200,
    maxHeight: 300,
    minWidth: 100,
    maxWidth: 300
  },
      el,
      body = document.body,
      text = document.createTextNode(''),
      span = document.createElement('SPAN'),
      observe = function observe(element, event, handler) {
    if (element.attachEvent) {
      element.attachEvent('on' + event, handler);
    } else {
      element.addEventListener(event, handler, false);
    }
  },
      _unObserve = function _unObserve(element, event, handler) {
    if (element.removeEventListener) {
      element.removeEventListener(event, handler, false);
    } else {
      element.detachEvent('on' + event, handler);
    }
  },
      resize = function resize(newChar) {
    var width, scrollHeight;

    if (!newChar) {
      newChar = "";
    } else if (!/^[a-zA-Z \.,\\\/\|0-9]$/.test(newChar)) {
      newChar = ".";
    }

    if (text.textContent !== void 0) {
      text.textContent = el.value + newChar;
    } else {
      text.data = el.value + newChar; //IE8
    }
    span.style.fontSize = getComputedStyle(el).fontSize;
    span.style.fontFamily = getComputedStyle(el).fontFamily;
    span.style.whiteSpace = "pre";

    body.appendChild(span);
    width = span.clientWidth + 2;
    body.removeChild(span);

    el.style.height = defaults.minHeight + 'px';

    if (defaults.minWidth > width) {
      el.style.width = defaults.minWidth + 'px';
    } else if (width > defaults.maxWidth) {
      el.style.width = defaults.maxWidth + 'px';
    } else {
      el.style.width = width + 'px';
    }
    scrollHeight = el.scrollHeight ? el.scrollHeight - 1 : 0;

    if (defaults.minHeight > scrollHeight) {
      el.style.height = defaults.minHeight + 'px';
    } else if (defaults.maxHeight < scrollHeight) {
      el.style.height = defaults.maxHeight + 'px';
      el.style.overflowY = 'visible';
    } else {
      el.style.height = scrollHeight + 'px';
    }
  },
      delayedResize = function delayedResize() {
    window.setTimeout(resize, 0);
  },
      extendDefaults = function extendDefaults(config) {

    if (config && config.minHeight) {
      if (config.minHeight == 'inherit') {
        defaults.minHeight = el.clientHeight;
      } else {
        var minHeight = parseInt(config.minHeight);
        if (!isNaN(minHeight)) {
          defaults.minHeight = minHeight;
        }
      }
    }

    if (config && config.maxHeight) {
      if (config.maxHeight == 'inherit') {
        defaults.maxHeight = el.clientHeight;
      } else {
        var maxHeight = parseInt(config.maxHeight);
        if (!isNaN(maxHeight)) {
          defaults.maxHeight = maxHeight;
        }
      }
    }

    if (config && config.minWidth) {
      if (config.minWidth == 'inherit') {
        defaults.minWidth = el.clientWidth;
      } else {
        var minWidth = parseInt(config.minWidth);
        if (!isNaN(minWidth)) {
          defaults.minWidth = minWidth;
        }
      }
    }

    if (config && config.maxWidth) {
      if (config.maxWidth == 'inherit') {
        defaults.maxWidth = el.clientWidth;
      } else {
        var maxWidth = parseInt(config.maxWidth);
        if (!isNaN(maxWidth)) {
          defaults.maxWidth = maxWidth;
        }
      }
    }

    if (!span.firstChild) {
      span.className = "autoResize";
      span.style.display = 'inline-block';
      span.appendChild(text);
    }
  },
      _init = function _init(el_, config, doObserve) {
    el = el_;
    extendDefaults(config);

    if (el.nodeName == 'TEXTAREA') {

      el.style.resize = 'none';
      el.style.overflowY = '';
      el.style.height = defaults.minHeight + 'px';
      el.style.minWidth = defaults.minWidth + 'px';
      el.style.maxWidth = defaults.maxWidth + 'px';
      el.style.overflowY = 'hidden';
    }

    if (doObserve) {
      observe(el, 'change', resize);
      observe(el, 'cut', delayedResize);
      observe(el, 'paste', delayedResize);
      observe(el, 'drop', delayedResize);
      observe(el, 'keydown', delayedResize);
      observe(el, 'focus', resize);
    }

    resize();
  };

  function getComputedStyle(element) {
    return element.currentStyle || document.defaultView.getComputedStyle(element);
  }

  return {
    init: function init(el_, config, doObserve) {
      _init(el_, config, doObserve);
    },
    unObserve: function unObserve() {
      _unObserve(el, 'change', resize);
      _unObserve(el, 'cut', delayedResize);
      _unObserve(el, 'paste', delayedResize);
      _unObserve(el, 'drop', delayedResize);
      _unObserve(el, 'keydown', delayedResize);
      _unObserve(el, 'focus', resize);
    },
    resize: resize
  };
}

if (true) {
  module.exports = autoResize;
}

/***/ }),
/* 307 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


exports.__esModule = true;

var _element = __webpack_require__(0);

var _base = __webpack_require__(29);

var _base2 = _interopRequireDefault(_base);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }

function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }

/**
 * A overlay that renders ALL available rows & columns positioned on top of the original Walkontable instance and all other overlays.
 * Used for debugging purposes to see if the other overlays (that render only part of the rows & columns) are positioned correctly
 *
 * @class DebugOverlay
 */
var DebugOverlay = function (_Overlay) {
  _inherits(DebugOverlay, _Overlay);

  /**
   * @param {Walkontable} wotInstance
   */
  function DebugOverlay(wotInstance) {
    _classCallCheck(this, DebugOverlay);

    var _this = _possibleConstructorReturn(this, (DebugOverlay.__proto__ || Object.getPrototypeOf(DebugOverlay)).call(this, wotInstance));

    _this.clone = _this.makeClone(_base2.default.CLONE_DEBUG);
    _this.clone.wtTable.holder.style.opacity = 0.4;
    _this.clone.wtTable.holder.style.textShadow = '0 0 2px #ff0000';

    (0, _element.addClass)(_this.clone.wtTable.holder.parentNode, 'wtDebugVisible');
    return _this;
  }

  return DebugOverlay;
}(_base2.default);

_base2.default.registerOverlay(_base2.default.CLONE_DEBUG, DebugOverlay);

exports.default = DebugOverlay;

/***/ }),
/* 308 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


exports.__esModule = true;

var _createClass = 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); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

var _element = __webpack_require__(0);

var _base = __webpack_require__(29);

var _base2 = _interopRequireDefault(_base);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }

function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }

/**
 * @class LeftOverlay
 */
var LeftOverlay = function (_Overlay) {
  _inherits(LeftOverlay, _Overlay);

  /**
   * @param {Walkontable} wotInstance
   */
  function LeftOverlay(wotInstance) {
    _classCallCheck(this, LeftOverlay);

    var _this = _possibleConstructorReturn(this, (LeftOverlay.__proto__ || Object.getPrototypeOf(LeftOverlay)).call(this, wotInstance));

    _this.clone = _this.makeClone(_base2.default.CLONE_LEFT);
    return _this;
  }

  /**
   * Checks if overlay should be fully rendered
   *
   * @returns {Boolean}
   */


  _createClass(LeftOverlay, [{
    key: 'shouldBeRendered',
    value: function shouldBeRendered() {
      return !!(this.wot.getSetting('fixedColumnsLeft') || this.wot.getSetting('rowHeaders').length);
    }

    /**
     * Updates the left overlay position
     */

  }, {
    key: 'resetFixedPosition',
    value: function resetFixedPosition() {
      if (!this.needFullRender || !this.wot.wtTable.holder.parentNode) {
        // removed from DOM
        return;
      }
      var overlayRoot = this.clone.wtTable.holder.parentNode;
      var headerPosition = 0;
      var preventOverflow = this.wot.getSetting('preventOverflow');

      if (this.trimmingContainer === window && (!preventOverflow || preventOverflow !== 'horizontal')) {
        var box = this.wot.wtTable.hider.getBoundingClientRect();
        var left = Math.ceil(box.left);
        var right = Math.ceil(box.right);
        var finalLeft = void 0;
        var finalTop = void 0;

        finalTop = this.wot.wtTable.hider.style.top;
        finalTop = finalTop === '' ? 0 : finalTop;

        if (left < 0 && right - overlayRoot.offsetWidth > 0) {
          finalLeft = -left;
        } else {
          finalLeft = 0;
        }
        headerPosition = finalLeft;
        finalLeft += 'px';

        (0, _element.setOverlayPosition)(overlayRoot, finalLeft, finalTop);
      } else {
        headerPosition = this.getScrollPosition();
        (0, _element.resetCssTransform)(overlayRoot);
      }
      this.adjustHeaderBordersPosition(headerPosition);

      this.adjustElementsSize();
    }

    /**
     * Sets the main overlay's horizontal scroll position
     *
     * @param {Number} pos
     */

  }, {
    key: 'setScrollPosition',
    value: function setScrollPosition(pos) {
      if (this.mainTableScrollableElement === window) {
        window.scrollTo(pos, (0, _element.getWindowScrollTop)());
      } else {
        this.mainTableScrollableElement.scrollLeft = pos;
      }
    }

    /**
     * Triggers onScroll hook callback
     */

  }, {
    key: 'onScroll',
    value: function onScroll() {
      this.wot.getSetting('onScrollVertically');
    }

    /**
     * Calculates total sum cells width
     *
     * @param {Number} from Column index which calculates started from
     * @param {Number} to Column index where calculation is finished
     * @returns {Number} Width sum
     */

  }, {
    key: 'sumCellSizes',
    value: function sumCellSizes(from, to) {
      var sum = 0;
      var defaultColumnWidth = this.wot.wtSettings.defaultColumnWidth;

      while (from < to) {
        sum += this.wot.wtTable.getStretchedColumnWidth(from) || defaultColumnWidth;
        from++;
      }

      return sum;
    }

    /**
     * Adjust overlay root element, childs and master table element sizes (width, height).
     *
     * @param {Boolean} [force=false]
     */

  }, {
    key: 'adjustElementsSize',
    value: function adjustElementsSize() {
      var force = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;

      this.updateTrimmingContainer();

      if (this.needFullRender || force) {
        this.adjustRootElementSize();
        this.adjustRootChildrenSize();

        if (!force) {
          this.areElementSizesAdjusted = true;
        }
      }
    }

    /**
     * Adjust overlay root element size (width and height).
     */

  }, {
    key: 'adjustRootElementSize',
    value: function adjustRootElementSize() {
      var masterHolder = this.wot.wtTable.holder;
      var scrollbarHeight = masterHolder.clientHeight === masterHolder.offsetHeight ? 0 : (0, _element.getScrollbarWidth)();
      var overlayRoot = this.clone.wtTable.holder.parentNode;
      var overlayRootStyle = overlayRoot.style;
      var preventOverflow = this.wot.getSetting('preventOverflow');
      var tableWidth = void 0;

      if (this.trimmingContainer !== window || preventOverflow === 'vertical') {
        var height = this.wot.wtViewport.getWorkspaceHeight() - scrollbarHeight;

        height = Math.min(height, (0, _element.innerHeight)(this.wot.wtTable.wtRootElement));

        overlayRootStyle.height = height + 'px';
      } else {
        overlayRootStyle.height = '';
      }

      this.clone.wtTable.holder.style.height = overlayRootStyle.height;

      tableWidth = (0, _element.outerWidth)(this.clone.wtTable.TABLE);
      overlayRootStyle.width = (tableWidth === 0 ? tableWidth : tableWidth + 4) + 'px';
    }

    /**
     * Adjust overlay root childs size
     */

  }, {
    key: 'adjustRootChildrenSize',
    value: function adjustRootChildrenSize() {
      var scrollbarWidth = (0, _element.getScrollbarWidth)();

      this.clone.wtTable.hider.style.height = this.hider.style.height;
      this.clone.wtTable.holder.style.height = this.clone.wtTable.holder.parentNode.style.height;

      if (scrollbarWidth === 0) {
        scrollbarWidth = 30;
      }
      this.clone.wtTable.holder.style.width = parseInt(this.clone.wtTable.holder.parentNode.style.width, 10) + scrollbarWidth + 'px';
    }

    /**
     * Adjust the overlay dimensions and position
     */

  }, {
    key: 'applyToDOM',
    value: function applyToDOM() {
      var total = this.wot.getSetting('totalColumns');

      if (!this.areElementSizesAdjusted) {
        this.adjustElementsSize();
      }
      if (typeof this.wot.wtViewport.columnsRenderCalculator.startPosition === 'number') {
        this.spreader.style.left = this.wot.wtViewport.columnsRenderCalculator.startPosition + 'px';
      } else if (total === 0) {
        this.spreader.style.left = '0';
      } else {
        throw new Error('Incorrect value of the columnsRenderCalculator');
      }
      this.spreader.style.right = '';

      if (this.needFullRender) {
        this.syncOverlayOffset();
      }
    }

    /**
     * Synchronize calculated top position to an element
     */

  }, {
    key: 'syncOverlayOffset',
    value: function syncOverlayOffset() {
      if (typeof this.wot.wtViewport.rowsRenderCalculator.startPosition === 'number') {
        this.clone.wtTable.spreader.style.top = this.wot.wtViewport.rowsRenderCalculator.startPosition + 'px';
      } else {
        this.clone.wtTable.spreader.style.top = '';
      }
    }

    /**
     * Scrolls horizontally to a column at the left edge of the viewport
     *
     * @param sourceCol {Number} Column index which you want to scroll to
     * @param [beyondRendered=false] {Boolean} if `true`, scrolls according to the bottom edge (top edge is by default)
     */

  }, {
    key: 'scrollTo',
    value: function scrollTo(sourceCol, beyondRendered) {
      var newX = this.getTableParentOffset();
      var sourceInstance = this.wot.cloneSource ? this.wot.cloneSource : this.wot;
      var mainHolder = sourceInstance.wtTable.holder;
      var scrollbarCompensation = 0;

      if (beyondRendered && mainHolder.offsetWidth !== mainHolder.clientWidth) {
        scrollbarCompensation = (0, _element.getScrollbarWidth)();
      }
      if (beyondRendered) {
        newX += this.sumCellSizes(0, sourceCol + 1);
        newX -= this.wot.wtViewport.getViewportWidth();
      } else {
        newX += this.sumCellSizes(this.wot.getSetting('fixedColumnsLeft'), sourceCol);
      }
      newX += scrollbarCompensation;

      this.setScrollPosition(newX);
    }

    /**
     * Gets table parent left position
     *
     * @returns {Number}
     */

  }, {
    key: 'getTableParentOffset',
    value: function getTableParentOffset() {
      var preventOverflow = this.wot.getSetting('preventOverflow');
      var offset = 0;

      if (!preventOverflow && this.trimmingContainer === window) {
        offset = this.wot.wtTable.holderOffset.left;
      }

      return offset;
    }

    /**
     * Gets the main overlay's horizontal scroll position
     *
     * @returns {Number} Main table's vertical scroll position
     */

  }, {
    key: 'getScrollPosition',
    value: function getScrollPosition() {
      return (0, _element.getScrollLeft)(this.mainTableScrollableElement);
    }

    /**
     * Adds css classes to hide the header border's header (cell-selection border hiding issue)
     *
     * @param {Number} position Header X position if trimming container is window or scroll top if not
     */

  }, {
    key: 'adjustHeaderBordersPosition',
    value: function adjustHeaderBordersPosition(position) {
      var masterParent = this.wot.wtTable.holder.parentNode;
      var rowHeaders = this.wot.getSetting('rowHeaders');
      var fixedColumnsLeft = this.wot.getSetting('fixedColumnsLeft');
      var totalRows = this.wot.getSetting('totalRows');

      if (totalRows) {
        (0, _element.removeClass)(masterParent, 'emptyRows');
      } else {
        (0, _element.addClass)(masterParent, 'emptyRows');
      }

      if (fixedColumnsLeft && !rowHeaders.length) {
        (0, _element.addClass)(masterParent, 'innerBorderLeft');
      } else if (!fixedColumnsLeft && rowHeaders.length) {
        var previousState = (0, _element.hasClass)(masterParent, 'innerBorderLeft');

        if (position) {
          (0, _element.addClass)(masterParent, 'innerBorderLeft');
        } else {
          (0, _element.removeClass)(masterParent, 'innerBorderLeft');
        }
        if (!previousState && position || previousState && !position) {
          this.wot.wtOverlays.adjustElementsSize();
        }
      }
    }
  }]);

  return LeftOverlay;
}(_base2.default);

_base2.default.registerOverlay(_base2.default.CLONE_LEFT, LeftOverlay);

exports.default = LeftOverlay;

/***/ }),
/* 309 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


exports.__esModule = true;

var _createClass = 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); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

var _element = __webpack_require__(0);

var _base = __webpack_require__(29);

var _base2 = _interopRequireDefault(_base);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }

function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }

/**
 * @class TopOverlay
 */
var TopOverlay = function (_Overlay) {
  _inherits(TopOverlay, _Overlay);

  /**
   * @param {Walkontable} wotInstance
   */
  function TopOverlay(wotInstance) {
    _classCallCheck(this, TopOverlay);

    var _this = _possibleConstructorReturn(this, (TopOverlay.__proto__ || Object.getPrototypeOf(TopOverlay)).call(this, wotInstance));

    _this.clone = _this.makeClone(_base2.default.CLONE_TOP);
    return _this;
  }

  /**
   * Checks if overlay should be fully rendered
   *
   * @returns {Boolean}
   */


  _createClass(TopOverlay, [{
    key: 'shouldBeRendered',
    value: function shouldBeRendered() {
      return !!(this.wot.getSetting('fixedRowsTop') || this.wot.getSetting('columnHeaders').length);
    }

    /**
     * Updates the top overlay position
     */

  }, {
    key: 'resetFixedPosition',
    value: function resetFixedPosition() {
      if (!this.needFullRender || !this.wot.wtTable.holder.parentNode) {
        // removed from DOM
        return;
      }
      var overlayRoot = this.clone.wtTable.holder.parentNode;
      var headerPosition = 0;
      var preventOverflow = this.wot.getSetting('preventOverflow');

      if (this.trimmingContainer === window && (!preventOverflow || preventOverflow !== 'vertical')) {
        var box = this.wot.wtTable.hider.getBoundingClientRect();
        var top = Math.ceil(box.top);
        var bottom = Math.ceil(box.bottom);
        var finalLeft = void 0;
        var finalTop = void 0;

        finalLeft = this.wot.wtTable.hider.style.left;
        finalLeft = finalLeft === '' ? 0 : finalLeft;

        if (top < 0 && bottom - overlayRoot.offsetHeight > 0) {
          finalTop = -top;
        } else {
          finalTop = 0;
        }
        headerPosition = finalTop;
        finalTop += 'px';

        (0, _element.setOverlayPosition)(overlayRoot, finalLeft, finalTop);
      } else {
        headerPosition = this.getScrollPosition();
        (0, _element.resetCssTransform)(overlayRoot);
      }

      this.adjustHeaderBordersPosition(headerPosition);

      this.adjustElementsSize();
    }

    /**
     * Sets the main overlay's vertical scroll position
     *
     * @param {Number} pos
     */

  }, {
    key: 'setScrollPosition',
    value: function setScrollPosition(pos) {
      if (this.mainTableScrollableElement === window) {
        window.scrollTo((0, _element.getWindowScrollLeft)(), pos);
      } else {
        this.mainTableScrollableElement.scrollTop = pos;
      }
    }

    /**
     * Triggers onScroll hook callback
     */

  }, {
    key: 'onScroll',
    value: function onScroll() {
      this.wot.getSetting('onScrollHorizontally');
    }

    /**
     * Calculates total sum cells height
     *
     * @param {Number} from Row index which calculates started from
     * @param {Number} to Row index where calculation is finished
     * @returns {Number} Height sum
     */

  }, {
    key: 'sumCellSizes',
    value: function sumCellSizes(from, to) {
      var sum = 0;
      var defaultRowHeight = this.wot.wtSettings.settings.defaultRowHeight;

      while (from < to) {
        var height = this.wot.wtTable.getRowHeight(from);

        sum += height === void 0 ? defaultRowHeight : height;
        from++;
      }

      return sum;
    }

    /**
     * Adjust overlay root element, childs and master table element sizes (width, height).
     *
     * @param {Boolean} [force=false]
     */

  }, {
    key: 'adjustElementsSize',
    value: function adjustElementsSize() {
      var force = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;

      this.updateTrimmingContainer();

      if (this.needFullRender || force) {
        this.adjustRootElementSize();
        this.adjustRootChildrenSize();

        if (!force) {
          this.areElementSizesAdjusted = true;
        }
      }
    }

    /**
     * Adjust overlay root element size (width and height).
     */

  }, {
    key: 'adjustRootElementSize',
    value: function adjustRootElementSize() {
      var masterHolder = this.wot.wtTable.holder;
      var scrollbarWidth = masterHolder.clientWidth === masterHolder.offsetWidth ? 0 : (0, _element.getScrollbarWidth)();
      var overlayRoot = this.clone.wtTable.holder.parentNode;
      var overlayRootStyle = overlayRoot.style;
      var preventOverflow = this.wot.getSetting('preventOverflow');
      var tableHeight = void 0;

      if (this.trimmingContainer !== window || preventOverflow === 'horizontal') {
        var width = this.wot.wtViewport.getWorkspaceWidth() - scrollbarWidth;

        width = Math.min(width, (0, _element.innerWidth)(this.wot.wtTable.wtRootElement));

        overlayRootStyle.width = width + 'px';
      } else {
        overlayRootStyle.width = '';
      }

      this.clone.wtTable.holder.style.width = overlayRootStyle.width;

      tableHeight = (0, _element.outerHeight)(this.clone.wtTable.TABLE);
      overlayRootStyle.height = (tableHeight === 0 ? tableHeight : tableHeight + 4) + 'px';
    }

    /**
     * Adjust overlay root childs size
     */

  }, {
    key: 'adjustRootChildrenSize',
    value: function adjustRootChildrenSize() {
      var scrollbarWidth = (0, _element.getScrollbarWidth)();

      this.clone.wtTable.hider.style.width = this.hider.style.width;
      this.clone.wtTable.holder.style.width = this.clone.wtTable.holder.parentNode.style.width;

      if (scrollbarWidth === 0) {
        scrollbarWidth = 30;
      }
      this.clone.wtTable.holder.style.height = parseInt(this.clone.wtTable.holder.parentNode.style.height, 10) + scrollbarWidth + 'px';
    }

    /**
     * Adjust the overlay dimensions and position
     */

  }, {
    key: 'applyToDOM',
    value: function applyToDOM() {
      var total = this.wot.getSetting('totalRows');

      if (!this.areElementSizesAdjusted) {
        this.adjustElementsSize();
      }
      if (typeof this.wot.wtViewport.rowsRenderCalculator.startPosition === 'number') {
        this.spreader.style.top = this.wot.wtViewport.rowsRenderCalculator.startPosition + 'px';
      } else if (total === 0) {
        // can happen if there are 0 rows
        this.spreader.style.top = '0';
      } else {
        throw new Error('Incorrect value of the rowsRenderCalculator');
      }
      this.spreader.style.bottom = '';

      if (this.needFullRender) {
        this.syncOverlayOffset();
      }
    }

    /**
     * Synchronize calculated left position to an element
     */

  }, {
    key: 'syncOverlayOffset',
    value: function syncOverlayOffset() {
      if (typeof this.wot.wtViewport.columnsRenderCalculator.startPosition === 'number') {
        this.clone.wtTable.spreader.style.left = this.wot.wtViewport.columnsRenderCalculator.startPosition + 'px';
      } else {
        this.clone.wtTable.spreader.style.left = '';
      }
    }

    /**
     * Scrolls vertically to a row
     *
     * @param sourceRow {Number} Row index which you want to scroll to
     * @param [bottomEdge=false] {Boolean} if `true`, scrolls according to the bottom edge (top edge is by default)
     */

  }, {
    key: 'scrollTo',
    value: function scrollTo(sourceRow, bottomEdge) {
      var newY = this.getTableParentOffset();
      var sourceInstance = this.wot.cloneSource ? this.wot.cloneSource : this.wot;
      var mainHolder = sourceInstance.wtTable.holder;
      var scrollbarCompensation = 0;

      if (bottomEdge && mainHolder.offsetHeight !== mainHolder.clientHeight) {
        scrollbarCompensation = (0, _element.getScrollbarWidth)();
      }

      if (bottomEdge) {
        var fixedRowsBottom = this.wot.getSetting('fixedRowsBottom');
        var fixedRowsTop = this.wot.getSetting('fixedRowsTop');
        var totalRows = this.wot.getSetting('totalRows');

        newY += this.sumCellSizes(0, sourceRow + 1);
        newY -= this.wot.wtViewport.getViewportHeight() - this.sumCellSizes(totalRows - fixedRowsBottom, totalRows);
        // Fix 1 pixel offset when cell is selected
        newY += 1;
      } else {
        newY += this.sumCellSizes(this.wot.getSetting('fixedRowsTop'), sourceRow);
      }
      newY += scrollbarCompensation;

      this.setScrollPosition(newY);
    }

    /**
     * Gets table parent top position
     *
     * @returns {Number}
     */

  }, {
    key: 'getTableParentOffset',
    value: function getTableParentOffset() {
      if (this.mainTableScrollableElement === window) {
        return this.wot.wtTable.holderOffset.top;
      }
      return 0;
    }

    /**
     * Gets the main overlay's vertical scroll position
     *
     * @returns {Number} Main table's vertical scroll position
     */

  }, {
    key: 'getScrollPosition',
    value: function getScrollPosition() {
      return (0, _element.getScrollTop)(this.mainTableScrollableElement);
    }

    /**
     * Redraw borders of selection
     *
     * @param {WalkontableSelection} selection Selection for redraw
     */

  }, {
    key: 'redrawSelectionBorders',
    value: function redrawSelectionBorders(selection) {
      if (selection && selection.cellRange) {
        var border = selection.getBorder(this.wot);

        if (border) {
          var corners = selection.getCorners();
          border.disappear();
          border.appear(corners);
        }
      }
    }

    /**
     * Redrawing borders of all selections
     */

  }, {
    key: 'redrawAllSelectionsBorders',
    value: function redrawAllSelectionsBorders() {
      var selections = this.wot.selections;

      this.redrawSelectionBorders(selections.current);
      this.redrawSelectionBorders(selections.area);
      this.redrawSelectionBorders(selections.fill);
      this.wot.wtTable.wot.wtOverlays.leftOverlay.refresh();
    }

    /**
     * Adds css classes to hide the header border's header (cell-selection border hiding issue)
     *
     * @param {Number} position Header Y position if trimming container is window or scroll top if not
     */

  }, {
    key: 'adjustHeaderBordersPosition',
    value: function adjustHeaderBordersPosition(position) {
      var masterParent = this.wot.wtTable.holder.parentNode;
      var totalColumns = this.wot.getSetting('totalColumns');

      if (totalColumns) {
        (0, _element.removeClass)(masterParent, 'emptyColumns');
      } else {
        (0, _element.addClass)(masterParent, 'emptyColumns');
      }

      if (this.wot.getSetting('fixedRowsTop') === 0 && this.wot.getSetting('columnHeaders').length > 0) {
        var previousState = (0, _element.hasClass)(masterParent, 'innerBorderTop');

        if (position || this.wot.getSetting('totalRows') === 0) {
          (0, _element.addClass)(masterParent, 'innerBorderTop');
        } else {
          (0, _element.removeClass)(masterParent, 'innerBorderTop');
        }

        if (!previousState && position || previousState && !position) {
          this.wot.wtOverlays.adjustElementsSize();

          // cell borders should be positioned once again,
          // because we added / removed 1px border from table header
          this.redrawAllSelectionsBorders();
        }
      }

      // nasty workaround for double border in the header, TODO: find a pure-css solution
      if (this.wot.getSetting('rowHeaders').length === 0) {
        var secondHeaderCell = this.clone.wtTable.THEAD.querySelectorAll('th:nth-of-type(2)');

        if (secondHeaderCell) {
          for (var i = 0; i < secondHeaderCell.length; i++) {
            secondHeaderCell[i].style['border-left-width'] = 0;
          }
        }
      }
    }
  }]);

  return TopOverlay;
}(_base2.default);

_base2.default.registerOverlay(_base2.default.CLONE_TOP, TopOverlay);

exports.default = TopOverlay;

/***/ }),
/* 310 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


exports.__esModule = true;

var _createClass = 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); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

var _element = __webpack_require__(0);

var _base = __webpack_require__(29);

var _base2 = _interopRequireDefault(_base);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }

function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }

/**
 * @class TopLeftCornerOverlay
 */
var TopLeftCornerOverlay = function (_Overlay) {
  _inherits(TopLeftCornerOverlay, _Overlay);

  /**
   * @param {Walkontable} wotInstance
   */
  function TopLeftCornerOverlay(wotInstance) {
    _classCallCheck(this, TopLeftCornerOverlay);

    var _this = _possibleConstructorReturn(this, (TopLeftCornerOverlay.__proto__ || Object.getPrototypeOf(TopLeftCornerOverlay)).call(this, wotInstance));

    _this.clone = _this.makeClone(_base2.default.CLONE_TOP_LEFT_CORNER);
    return _this;
  }

  /**
   * Checks if overlay should be fully rendered
   *
   * @returns {Boolean}
   */


  _createClass(TopLeftCornerOverlay, [{
    key: 'shouldBeRendered',
    value: function shouldBeRendered() {
      return !!((this.wot.getSetting('fixedRowsTop') || this.wot.getSetting('columnHeaders').length) && (this.wot.getSetting('fixedColumnsLeft') || this.wot.getSetting('rowHeaders').length));
    }

    /**
     * Updates the corner overlay position
     */

  }, {
    key: 'resetFixedPosition',
    value: function resetFixedPosition() {
      this.updateTrimmingContainer();

      if (!this.wot.wtTable.holder.parentNode) {
        // removed from DOM
        return;
      }
      var overlayRoot = this.clone.wtTable.holder.parentNode;
      var tableHeight = (0, _element.outerHeight)(this.clone.wtTable.TABLE);
      var tableWidth = (0, _element.outerWidth)(this.clone.wtTable.TABLE);
      var preventOverflow = this.wot.getSetting('preventOverflow');

      if (this.trimmingContainer === window) {
        var box = this.wot.wtTable.hider.getBoundingClientRect();
        var top = Math.ceil(box.top);
        var left = Math.ceil(box.left);
        var bottom = Math.ceil(box.bottom);
        var right = Math.ceil(box.right);
        var finalLeft = '0';
        var finalTop = '0';

        if (!preventOverflow || preventOverflow === 'vertical') {
          if (left < 0 && right - overlayRoot.offsetWidth > 0) {
            finalLeft = -left + 'px';
          }
        }

        if (!preventOverflow || preventOverflow === 'horizontal') {
          if (top < 0 && bottom - overlayRoot.offsetHeight > 0) {
            finalTop = -top + 'px';
          }
        }
        (0, _element.setOverlayPosition)(overlayRoot, finalLeft, finalTop);
      } else {
        (0, _element.resetCssTransform)(overlayRoot);
      }
      overlayRoot.style.height = (tableHeight === 0 ? tableHeight : tableHeight + 4) + 'px';
      overlayRoot.style.width = (tableWidth === 0 ? tableWidth : tableWidth + 4) + 'px';
    }
  }]);

  return TopLeftCornerOverlay;
}(_base2.default);

_base2.default.registerOverlay(_base2.default.CLONE_TOP_LEFT_CORNER, TopLeftCornerOverlay);

exports.default = TopLeftCornerOverlay;

/***/ }),
/* 311 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


exports.__esModule = true;

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

var _createClass = 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); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

var _element = __webpack_require__(0);

var _border2 = __webpack_require__(250);

var _border3 = _interopRequireDefault(_border2);

var _coords = __webpack_require__(43);

var _coords2 = _interopRequireDefault(_coords);

var _range = __webpack_require__(71);

var _range2 = _interopRequireDefault(_range);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

/**
 * @class Selection
 */
var Selection = function () {
  /**
   * @param {Object} settings
   * @param {CellRange} cellRange
   */
  function Selection(settings, cellRange) {
    _classCallCheck(this, Selection);

    this.settings = settings;
    this.cellRange = cellRange || null;
    this.instanceBorders = {};
  }

  /**
   * Each Walkontable clone requires it's own border for every selection. This method creates and returns selection
   * borders per instance
   *
   * @param {Walkontable} wotInstance
   * @returns {Border}
   */


  _createClass(Selection, [{
    key: 'getBorder',
    value: function getBorder(wotInstance) {
      if (this.instanceBorders[wotInstance.guid]) {
        return this.instanceBorders[wotInstance.guid];
      }

      // where is this returned?
      this.instanceBorders[wotInstance.guid] = new _border3.default(wotInstance, this.settings);
    }

    /**
     * Checks if selection is empty
     *
     * @returns {Boolean}
     */

  }, {
    key: 'isEmpty',
    value: function isEmpty() {
      return this.cellRange === null;
    }

    /**
     * Adds a cell coords to the selection
     *
     * @param {CellCoords} coords
     */

  }, {
    key: 'add',
    value: function add(coords) {
      if (this.isEmpty()) {
        this.cellRange = new _range2.default(coords, coords, coords);
      } else {
        this.cellRange.expand(coords);
      }
    }

    /**
     * If selection range from or to property equals oldCoords, replace it with newCoords. Return boolean
     * information about success
     *
     * @param {CellCoords} oldCoords
     * @param {CellCoords} newCoords
     * @returns {Boolean}
     */

  }, {
    key: 'replace',
    value: function replace(oldCoords, newCoords) {
      if (!this.isEmpty()) {
        if (this.cellRange.from.isEqual(oldCoords)) {
          this.cellRange.from = newCoords;

          return true;
        }
        if (this.cellRange.to.isEqual(oldCoords)) {
          this.cellRange.to = newCoords;

          return true;
        }
      }

      return false;
    }

    /**
     * Clears selection
     */

  }, {
    key: 'clear',
    value: function clear() {
      this.cellRange = null;
    }

    /**
     * Returns the top left (TL) and bottom right (BR) selection coordinates
     *
     * @returns {Array} Returns array of coordinates for example `[1, 1, 5, 5]`
     */

  }, {
    key: 'getCorners',
    value: function getCorners() {
      var topLeft = this.cellRange.getTopLeftCorner();
      var bottomRight = this.cellRange.getBottomRightCorner();

      return [topLeft.row, topLeft.col, bottomRight.row, bottomRight.col];
    }

    /**
     * Adds class name to cell element at given coords
     *
     * @param {Walkontable} wotInstance Walkontable instance
     * @param {Number} sourceRow Cell row coord
     * @param {Number} sourceColumn Cell column coord
     * @param {String} className Class name
     */

  }, {
    key: 'addClassAtCoords',
    value: function addClassAtCoords(wotInstance, sourceRow, sourceColumn, className) {
      var TD = wotInstance.wtTable.getCell(new _coords2.default(sourceRow, sourceColumn));

      if ((typeof TD === 'undefined' ? 'undefined' : _typeof(TD)) === 'object') {
        (0, _element.addClass)(TD, className);
      }
    }

    /**
     * @param wotInstance
     */

  }, {
    key: 'draw',
    value: function draw(wotInstance) {
      if (this.isEmpty()) {
        if (this.settings.border) {
          var border = this.getBorder(wotInstance);

          if (border) {
            border.disappear();
          }
        }

        return;
      }
      var renderedRows = wotInstance.wtTable.getRenderedRowsCount();
      var renderedColumns = wotInstance.wtTable.getRenderedColumnsCount();
      var corners = this.getCorners();
      var sourceRow = void 0,
          sourceCol = void 0,
          TH = void 0;

      for (var column = 0; column < renderedColumns; column++) {
        sourceCol = wotInstance.wtTable.columnFilter.renderedToSource(column);

        if (sourceCol >= corners[1] && sourceCol <= corners[3]) {
          TH = wotInstance.wtTable.getColumnHeader(sourceCol);

          if (TH) {
            var newClasses = [];

            if (this.settings.highlightHeaderClassName) {
              newClasses.push(this.settings.highlightHeaderClassName);
            }

            if (this.settings.highlightColumnClassName) {
              newClasses.push(this.settings.highlightColumnClassName);
            }

            (0, _element.addClass)(TH, newClasses);
          }
        }
      }

      for (var row = 0; row < renderedRows; row++) {
        sourceRow = wotInstance.wtTable.rowFilter.renderedToSource(row);

        if (sourceRow >= corners[0] && sourceRow <= corners[2]) {
          TH = wotInstance.wtTable.getRowHeader(sourceRow);

          if (TH) {
            var _newClasses = [];

            if (this.settings.highlightHeaderClassName) {
              _newClasses.push(this.settings.highlightHeaderClassName);
            }

            if (this.settings.highlightRowClassName) {
              _newClasses.push(this.settings.highlightRowClassName);
            }

            (0, _element.addClass)(TH, _newClasses);
          }
        }

        for (var _column = 0; _column < renderedColumns; _column++) {
          sourceCol = wotInstance.wtTable.columnFilter.renderedToSource(_column);

          if (sourceRow >= corners[0] && sourceRow <= corners[2] && sourceCol >= corners[1] && sourceCol <= corners[3]) {
            // selected cell
            if (this.settings.className) {
              this.addClassAtCoords(wotInstance, sourceRow, sourceCol, this.settings.className);
            }
          } else if (sourceRow >= corners[0] && sourceRow <= corners[2]) {
            // selection is in this row
            if (this.settings.highlightRowClassName) {
              this.addClassAtCoords(wotInstance, sourceRow, sourceCol, this.settings.highlightRowClassName);
            }
          } else if (sourceCol >= corners[1] && sourceCol <= corners[3]) {
            // selection is in this column
            if (this.settings.highlightColumnClassName) {
              this.addClassAtCoords(wotInstance, sourceRow, sourceCol, this.settings.highlightColumnClassName);
            }
          }
        }
      }
      wotInstance.getSetting('onBeforeDrawBorders', corners, this.settings.className);

      if (this.settings.border) {
        var _border = this.getBorder(wotInstance);

        if (_border) {
          // warning! border.appear modifies corners!
          _border.appear(corners);
        }
      }
    }
  }]);

  return Selection;
}();

exports.default = Selection;

/***/ }),
/* 312 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


exports.__esModule = true;

var _editors = __webpack_require__(13);

var _renderers = __webpack_require__(6);

var _validators = __webpack_require__(24);

var CELL_TYPE = 'autocomplete';

exports.default = {
  editor: (0, _editors.getEditor)(CELL_TYPE),
  renderer: (0, _renderers.getRenderer)(CELL_TYPE),
  validator: (0, _validators.getValidator)(CELL_TYPE)
};

/***/ }),
/* 313 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


exports.__esModule = true;

var _editors = __webpack_require__(13);

var _renderers = __webpack_require__(6);

var CELL_TYPE = 'checkbox';

exports.default = {
  editor: (0, _editors.getEditor)(CELL_TYPE),
  renderer: (0, _renderers.getRenderer)(CELL_TYPE)
};

/***/ }),
/* 314 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


exports.__esModule = true;

var _editors = __webpack_require__(13);

var _renderers = __webpack_require__(6);

var _validators = __webpack_require__(24);

var CELL_TYPE = 'date';

exports.default = {
  editor: (0, _editors.getEditor)(CELL_TYPE),
  // displays small gray arrow on right side of the cell
  renderer: (0, _renderers.getRenderer)('autocomplete'),
  validator: (0, _validators.getValidator)(CELL_TYPE)
};

/***/ }),
/* 315 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


exports.__esModule = true;

var _editors = __webpack_require__(13);

var _renderers = __webpack_require__(6);

var _validators = __webpack_require__(24);

var CELL_TYPE = 'dropdown';

exports.default = {
  editor: (0, _editors.getEditor)(CELL_TYPE),
  // displays small gray arrow on right side of the cell
  renderer: (0, _renderers.getRenderer)('autocomplete'),
  validator: (0, _validators.getValidator)('autocomplete')
};

/***/ }),
/* 316 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


exports.__esModule = true;

var _editors = __webpack_require__(13);

var _renderers = __webpack_require__(6);

var CELL_TYPE = 'handsontable';

exports.default = {
  editor: (0, _editors.getEditor)(CELL_TYPE),
  // displays small gray arrow on right side of the cell
  renderer: (0, _renderers.getRenderer)('autocomplete')
};

/***/ }),
/* 317 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


exports.__esModule = true;

var _editors = __webpack_require__(13);

var _renderers = __webpack_require__(6);

var _validators = __webpack_require__(24);

var CELL_TYPE = 'numeric';

exports.default = {
  editor: (0, _editors.getEditor)(CELL_TYPE),
  renderer: (0, _renderers.getRenderer)(CELL_TYPE),
  validator: (0, _validators.getValidator)(CELL_TYPE),
  dataType: 'number'
};

/***/ }),
/* 318 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


exports.__esModule = true;

var _editors = __webpack_require__(13);

var _renderers = __webpack_require__(6);

var _validators = __webpack_require__(24);

var CELL_TYPE = 'password';

exports.default = {
  editor: (0, _editors.getEditor)(CELL_TYPE),
  renderer: (0, _renderers.getRenderer)(CELL_TYPE),
  copyable: false
};

/***/ }),
/* 319 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


exports.__esModule = true;

var _browser = __webpack_require__(22);

var _editors = __webpack_require__(13);

var _renderers = __webpack_require__(6);

var CELL_TYPE = 'text';

exports.default = {
  editor: (0, _browser.isMobileBrowser)() ? (0, _editors.getEditor)('mobile') : (0, _editors.getEditor)(CELL_TYPE),
  renderer: (0, _renderers.getRenderer)(CELL_TYPE)
};

/***/ }),
/* 320 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


exports.__esModule = true;

var _editors = __webpack_require__(13);

var _renderers = __webpack_require__(6);

var _validators = __webpack_require__(24);

var CELL_TYPE = 'time';

exports.default = {
  editor: (0, _editors.getEditor)('text'),
  // displays small gray arrow on right side of the cell
  renderer: (0, _renderers.getRenderer)('text'),
  validator: (0, _validators.getValidator)(CELL_TYPE)
};

/***/ }),
/* 321 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


exports.__esModule = true;

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

var _SheetClip = __webpack_require__(249);

var _SheetClip2 = _interopRequireDefault(_SheetClip);

var _data = __webpack_require__(67);

var _setting = __webpack_require__(68);

var _object = __webpack_require__(3);

var _array = __webpack_require__(2);

var _interval = __webpack_require__(384);

var _interval2 = _interopRequireDefault(_interval);

var _number = __webpack_require__(5);

var _multiMap = __webpack_require__(334);

var _multiMap2 = _interopRequireDefault(_multiMap);

var _pluginHooks = __webpack_require__(11);

var _pluginHooks2 = _interopRequireDefault(_pluginHooks);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

/**
 * Utility class that gets and saves data from/to the data source using mapping of columns numbers to object property names
 * @todo refactor arguments of methods getRange, getText to be numbers (not objects)
 * @todo remove priv, GridSettings from object constructor
 *
 * @param {Object} instance Instance of Handsontable
 * @param {*} priv
 * @param {*} GridSettings Grid settings
 * @util
 * @class DataMap
 */
function DataMap(instance, priv, GridSettings) {
  var _this = this;

  this.instance = instance;
  this.priv = priv;
  this.GridSettings = GridSettings;
  this.dataSource = this.instance.getSettings().data;
  this.cachedLength = null;
  this.skipCache = false;
  this.latestSourceRowsCount = 0;

  if (this.dataSource && this.dataSource[0]) {
    this.duckSchema = this.recursiveDuckSchema(this.dataSource[0]);
  } else {
    this.duckSchema = {};
  }
  this.createMap();
  this.interval = _interval2.default.create(function () {
    return _this.clearLengthCache();
  }, '15fps');

  this.instance.addHook('skipLengthCache', function (delay) {
    return _this.onSkipLengthCache(delay);
  });
  this.onSkipLengthCache(500);
}

DataMap.prototype.DESTINATION_RENDERER = 1;
DataMap.prototype.DESTINATION_CLIPBOARD_GENERATOR = 2;

/**
 * @param {Object|Array} object
 * @returns {Object|Array}
 */
DataMap.prototype.recursiveDuckSchema = function (object) {
  return (0, _object.duckSchema)(object);
};

/**
 * @param {Object} schema
 * @param {Number} lastCol
 * @param {Number} parent
 * @returns {Number}
 */
DataMap.prototype.recursiveDuckColumns = function (schema, lastCol, parent) {
  var prop, i;
  if (typeof lastCol === 'undefined') {
    lastCol = 0;
    parent = '';
  }
  if ((typeof schema === 'undefined' ? 'undefined' : _typeof(schema)) === 'object' && !Array.isArray(schema)) {
    for (i in schema) {
      if ((0, _object.hasOwnProperty)(schema, i)) {
        if (schema[i] === null) {
          prop = parent + i;
          this.colToPropCache.push(prop);
          this.propToColCache.set(prop, lastCol);

          lastCol++;
        } else {
          lastCol = this.recursiveDuckColumns(schema[i], lastCol, i + '.');
        }
      }
    }
  }

  return lastCol;
};

DataMap.prototype.createMap = function () {
  var i = void 0;
  var schema = this.getSchema();

  if (typeof schema === 'undefined') {
    throw new Error('trying to create `columns` definition but you didn\'t provide `schema` nor `data`');
  }

  this.colToPropCache = [];
  this.propToColCache = new _multiMap2.default();

  var columns = this.instance.getSettings().columns;

  if (columns) {
    var maxCols = this.instance.getSettings().maxCols;
    var columnsLen = Math.min(maxCols, columns.length);
    var filteredIndex = 0;
    var columnsAsFunc = false;
    var schemaLen = (0, _object.deepObjectSize)(schema);

    if (typeof columns === 'function') {
      columnsLen = schemaLen > 0 ? schemaLen : this.instance.countSourceCols();
      columnsAsFunc = true;
    }

    for (i = 0; i < columnsLen; i++) {
      var column = columnsAsFunc ? columns(i) : columns[i];

      if ((0, _object.isObject)(column)) {
        if (typeof column.data !== 'undefined') {
          var index = columnsAsFunc ? filteredIndex : i;
          this.colToPropCache[index] = column.data;
          this.propToColCache.set(column.data, index);
        }

        filteredIndex++;
      }
    }
  } else {
    this.recursiveDuckColumns(schema);
  }
};

/**
 * Returns property name that corresponds with the given column index.
 *
 * @param {Number} col Visual column index.
 * @returns {Number} Physical column index.
 */
DataMap.prototype.colToProp = function (col) {
  col = this.instance.runHooks('modifyCol', col);

  if (!isNaN(col) && this.colToPropCache && typeof this.colToPropCache[col] !== 'undefined') {
    return this.colToPropCache[col];
  }

  return col;
};

/**
 * @param {Object} prop
 * @fires Hooks#modifyCol
 * @returns {*}
 */
DataMap.prototype.propToCol = function (prop) {
  var col;

  if (typeof this.propToColCache.get(prop) === 'undefined') {
    col = prop;
  } else {
    col = this.propToColCache.get(prop);
  }
  col = this.instance.runHooks('unmodifyCol', col);

  return col;
};

/**
 * @returns {Object}
 */
DataMap.prototype.getSchema = function () {
  var schema = this.instance.getSettings().dataSchema;

  if (schema) {
    if (typeof schema === 'function') {
      return schema();
    }
    return schema;
  }

  return this.duckSchema;
};

/**
 * Creates row at the bottom of the data array.
 *
 * @param {Number} [index] Physical index of the row before which the new row will be inserted.
 * @param {Number} [amount] An amount of rows to add.
 * @param {String} [source] Source of method call.
 * @fires Hooks#afterCreateRow
 * @returns {Number} Returns number of created rows.
 */
DataMap.prototype.createRow = function (index, amount, source) {
  var row,
      colCount = this.instance.countCols(),
      numberOfCreatedRows = 0,
      currentIndex;

  if (!amount) {
    amount = 1;
  }

  if (typeof index !== 'number' || index >= this.instance.countSourceRows()) {
    index = this.instance.countSourceRows();
  }
  this.instance.runHooks('beforeCreateRow', index, amount, source);

  currentIndex = index;
  var maxRows = this.instance.getSettings().maxRows;

  while (numberOfCreatedRows < amount && this.instance.countSourceRows() < maxRows) {
    if (this.instance.dataType === 'array') {
      if (this.instance.getSettings().dataSchema) {
        // Clone template array
        row = (0, _object.deepClone)(this.getSchema());
      } else {
        row = [];
        /* eslint-disable no-loop-func */
        (0, _number.rangeEach)(colCount - 1, function () {
          return row.push(null);
        });
      }
    } else if (this.instance.dataType === 'function') {
      row = this.instance.getSettings().dataSchema(index);
    } else {
      row = {};
      (0, _object.deepExtend)(row, this.getSchema());
    }

    if (index === this.instance.countSourceRows()) {
      this.dataSource.push(row);
    } else {
      this.spliceData(index, 0, row);
    }

    numberOfCreatedRows++;
    currentIndex++;
  }

  this.instance.runHooks('afterCreateRow', index, numberOfCreatedRows, source);
  this.instance.forceFullRender = true; // used when data was changed

  return numberOfCreatedRows;
};

/**
 * Creates col at the right of the data array.
 *
 * @param {Number} [index] Visual index of the column before which the new column will be inserted
 * @param {Number} [amount] An amount of columns to add.
 * @param {String} [source] Source of method call.
 * @fires Hooks#afterCreateCol
 * @returns {Number} Returns number of created columns
 */
DataMap.prototype.createCol = function (index, amount, source) {
  if (!this.instance.isColumnModificationAllowed()) {
    throw new Error('Cannot create new column. When data source in an object, ' + 'you can only have as much columns as defined in first data row, data schema or in the \'columns\' setting.' + 'If you want to be able to add new columns, you have to use array datasource.');
  }
  var rlen = this.instance.countSourceRows(),
      data = this.dataSource,
      constructor,
      numberOfCreatedCols = 0,
      currentIndex;

  if (!amount) {
    amount = 1;
  }

  if (typeof index !== 'number' || index >= this.instance.countCols()) {
    index = this.instance.countCols();
  }
  this.instance.runHooks('beforeCreateCol', index, amount, source);

  currentIndex = index;

  var maxCols = this.instance.getSettings().maxCols;
  while (numberOfCreatedCols < amount && this.instance.countCols() < maxCols) {
    constructor = (0, _setting.columnFactory)(this.GridSettings, this.priv.columnsSettingConflicts);

    if (typeof index !== 'number' || index >= this.instance.countCols()) {
      if (rlen > 0) {
        for (var r = 0; r < rlen; r++) {
          if (typeof data[r] === 'undefined') {
            data[r] = [];
          }
          data[r].push(null);
        }
      } else {
        data.push([null]);
      }
      // Add new column constructor
      this.priv.columnSettings.push(constructor);
    } else {
      for (var _r = 0; _r < rlen; _r++) {
        data[_r].splice(currentIndex, 0, null);
      }
      // Add new column constructor at given index
      this.priv.columnSettings.splice(currentIndex, 0, constructor);
    }

    numberOfCreatedCols++;
    currentIndex++;
  }

  this.instance.runHooks('afterCreateCol', index, numberOfCreatedCols, source);
  this.instance.forceFullRender = true; // used when data was changed

  return numberOfCreatedCols;
};

/**
 * Removes row from the data array.
 *
 * @param {Number} [index] Visual index of the row to be removed. If not provided, the last row will be removed
 * @param {Number} [amount] Amount of the rows to be removed. If not provided, one row will be removed
 * @param {String} [source] Source of method call.
 * @fires Hooks#beforeRemoveRow
 * @fires Hooks#afterRemoveRow
 */
DataMap.prototype.removeRow = function (index, amount, source) {
  if (!amount) {
    amount = 1;
  }
  if (typeof index !== 'number') {
    index = -amount;
  }

  amount = this.instance.runHooks('modifyRemovedAmount', amount, index);

  index = (this.instance.countSourceRows() + index) % this.instance.countSourceRows();

  var logicRows = this.visualRowsToPhysical(index, amount);
  var actionWasNotCancelled = this.instance.runHooks('beforeRemoveRow', index, amount, logicRows, source);

  if (actionWasNotCancelled === false) {
    return;
  }

  var data = this.dataSource;
  var newData = void 0;

  newData = this.filterData(index, amount);

  if (newData) {
    data.length = 0;
    Array.prototype.push.apply(data, newData);
  }

  this.instance.runHooks('afterRemoveRow', index, amount, logicRows, source);

  this.instance.forceFullRender = true; // used when data was changed
};

/**
 * Removes column from the data array.
 *
 * @param {Number} [index] Visual index of the column to be removed. If not provided, the last column will be removed
 * @param {Number} [amount] Amount of the columns to be removed. If not provided, one column will be removed
 * @param {String} [source] Source of method call.
 * @fires Hooks#beforeRemoveCol
 * @fires Hooks#afterRemoveCol
 */
DataMap.prototype.removeCol = function (index, amount, source) {
  if (this.instance.dataType === 'object' || this.instance.getSettings().columns) {
    throw new Error('cannot remove column with object data source or columns option specified');
  }
  if (!amount) {
    amount = 1;
  }
  if (typeof index !== 'number') {
    index = -amount;
  }

  index = (this.instance.countCols() + index) % this.instance.countCols();

  var logicColumns = this.visualColumnsToPhysical(index, amount);
  var descendingLogicColumns = logicColumns.slice(0).sort(function (a, b) {
    return b - a;
  });
  var actionWasNotCancelled = this.instance.runHooks('beforeRemoveCol', index, amount, logicColumns, source);

  if (actionWasNotCancelled === false) {
    return;
  }

  var isTableUniform = true;
  var removedColumnsCount = descendingLogicColumns.length;
  var data = this.dataSource;

  for (var c = 0; c < removedColumnsCount; c++) {
    if (isTableUniform && logicColumns[0] !== logicColumns[c] - c) {
      isTableUniform = false;
    }
  }

  if (isTableUniform) {
    for (var r = 0, rlen = this.instance.countSourceRows(); r < rlen; r++) {
      data[r].splice(logicColumns[0], amount);
    }
  } else {
    for (var _r2 = 0, _rlen = this.instance.countSourceRows(); _r2 < _rlen; _r2++) {
      for (var _c = 0; _c < removedColumnsCount; _c++) {
        data[_r2].splice(descendingLogicColumns[_c], 1);
      }
    }

    for (var _c2 = 0; _c2 < removedColumnsCount; _c2++) {
      this.priv.columnSettings.splice(logicColumns[_c2], 1);
    }
  }

  this.instance.runHooks('afterRemoveCol', index, amount, logicColumns, source);

  this.instance.forceFullRender = true; // used when data was changed
};

/**
 * Add/Removes data from the column.
 *
 * @param {Number} col Physical index of column in which do you want to do splice
 * @param {Number} index Index at which to start changing the array. If negative, will begin that many elements from the end
 * @param {Number} amount An integer indicating the number of old array elements to remove. If amount is 0, no elements are removed
 * @returns {Array} Returns removed portion of columns
 */
DataMap.prototype.spliceCol = function (col, index, amount /* , elements... */) {
  var elements = arguments.length >= 4 ? [].slice.call(arguments, 3) : [];

  var colData = this.instance.getDataAtCol(col);
  var removed = colData.slice(index, index + amount);
  var after = colData.slice(index + amount);

  (0, _array.extendArray)(elements, after);
  var i = 0;
  while (i < amount) {
    elements.push(null); // add null in place of removed elements
    i++;
  }
  (0, _array.to2dArray)(elements);
  this.instance.populateFromArray(index, col, elements, null, null, 'spliceCol');

  return removed;
};

/**
 * Add/Removes data from the row.
 *
 * @param {Number} row Physical index of row in which do you want to do splice
 * @param {Number} index Index at which to start changing the array. If negative, will begin that many elements from the end.
 * @param {Number} amount An integer indicating the number of old array elements to remove. If amount is 0, no elements are removed.
 * @returns {Array} Returns removed portion of rows
 */
DataMap.prototype.spliceRow = function (row, index, amount /* , elements... */) {
  var elements = arguments.length >= 4 ? [].slice.call(arguments, 3) : [];

  var rowData = this.instance.getSourceDataAtRow(row);
  var removed = rowData.slice(index, index + amount);
  var after = rowData.slice(index + amount);

  (0, _array.extendArray)(elements, after);
  var i = 0;
  while (i < amount) {
    elements.push(null); // add null in place of removed elements
    i++;
  }
  this.instance.populateFromArray(row, index, [elements], null, null, 'spliceRow');

  return removed;
};

/**
 * Add/remove row(s) to/from the data source.
 *
 * @param {Number} index Physical index of the element to remove.
 * @param {Number} amount Number of rows to add/remove.
 * @param {Object} element Row to add.
 */
DataMap.prototype.spliceData = function (index, amount, element) {
  var continueSplicing = this.instance.runHooks('beforeDataSplice', index, amount, element);

  if (continueSplicing !== false) {
    this.dataSource.splice(index, amount, element);
  }
};

/**
 * Filter unwanted data elements from the data source.
 *
 * @param {Number} index Visual index of the element to remove.
 * @param {Number} amount Number of rows to add/remove.
 * @returns {Array}
 */
DataMap.prototype.filterData = function (index, amount) {
  var physicalRows = this.visualRowsToPhysical(index, amount);
  var continueSplicing = this.instance.runHooks('beforeDataFilter', index, amount, physicalRows);

  if (continueSplicing !== false) {
    var newData = this.dataSource.filter(function (row, index) {
      return physicalRows.indexOf(index) == -1;
    });

    return newData;
  }
};

/**
 * Returns single value from the data array.
 *
 * @param {Number} row Visual row index.
 * @param {Number} prop
 */
DataMap.prototype.get = function (row, prop) {
  row = this.instance.runHooks('modifyRow', row);

  var dataRow = this.dataSource[row];
  // TODO: To remove, use 'modifyData' hook instead (see below)
  var modifiedRowData = this.instance.runHooks('modifyRowData', row);

  dataRow = isNaN(modifiedRowData) ? modifiedRowData : dataRow;
  //

  var value = null;

  // try to get value under property `prop` (includes dot)
  if (dataRow && dataRow.hasOwnProperty && (0, _object.hasOwnProperty)(dataRow, prop)) {
    value = dataRow[prop];
  } else if (typeof prop === 'string' && prop.indexOf('.') > -1) {
    var sliced = prop.split('.');
    var out = dataRow;

    if (!out) {
      return null;
    }
    for (var i = 0, ilen = sliced.length; i < ilen; i++) {
      out = out[sliced[i]];

      if (typeof out === 'undefined') {
        return null;
      }
    }
    value = out;
  } else if (typeof prop === 'function') {
    /**
     *  allows for interacting with complex structures, for example
     *  d3/jQuery getter/setter properties:
     *
     *    {columns: [{
     *      data: function(row, value){
     *        if(arguments.length === 1){
     *          return row.property();
     *        }
     *        row.property(value);
     *      }
     *    }]}
     */
    value = prop(this.dataSource.slice(row, row + 1)[0]);
  }

  if (this.instance.hasHook('modifyData')) {
    var valueHolder = (0, _object.createObjectPropListener)(value);

    this.instance.runHooks('modifyData', row, this.propToCol(prop), valueHolder, 'get');

    if (valueHolder.isTouched()) {
      value = valueHolder.value;
    }
  }

  return value;
};

var copyableLookup = (0, _data.cellMethodLookupFactory)('copyable', false);

/**
 * Returns single value from the data array (intended for clipboard copy to an external application).
 *
 * @param {Number} row Physical row index.
 * @param {Number} prop
 * @returns {String}
 */
DataMap.prototype.getCopyable = function (row, prop) {
  if (copyableLookup.call(this.instance, row, this.propToCol(prop))) {
    return this.get(row, prop);
  }
  return '';
};

/**
 * Saves single value to the data array.
 *
 * @param {Number} row Visual row index.
 * @param {Number} prop
 * @param {String} value
 * @param {String} [source] Source of hook runner.
 */
DataMap.prototype.set = function (row, prop, value, source) {
  row = this.instance.runHooks('modifyRow', row, source || 'datamapGet');

  var dataRow = this.dataSource[row];
  // TODO: To remove, use 'modifyData' hook instead (see below)
  var modifiedRowData = this.instance.runHooks('modifyRowData', row);

  dataRow = isNaN(modifiedRowData) ? modifiedRowData : dataRow;
  //

  if (this.instance.hasHook('modifyData')) {
    var valueHolder = (0, _object.createObjectPropListener)(value);

    this.instance.runHooks('modifyData', row, this.propToCol(prop), valueHolder, 'set');

    if (valueHolder.isTouched()) {
      value = valueHolder.value;
    }
  }

  // try to set value under property `prop` (includes dot)
  if (dataRow && dataRow.hasOwnProperty && (0, _object.hasOwnProperty)(dataRow, prop)) {
    dataRow[prop] = value;
  } else if (typeof prop === 'string' && prop.indexOf('.') > -1) {
    var sliced = prop.split('.');
    var out = dataRow;
    var i = 0;
    var ilen = void 0;

    for (i = 0, ilen = sliced.length - 1; i < ilen; i++) {
      if (typeof out[sliced[i]] === 'undefined') {
        out[sliced[i]] = {};
      }
      out = out[sliced[i]];
    }
    out[sliced[i]] = value;
  } else if (typeof prop === 'function') {
    /* see the `function` handler in `get` */
    prop(this.dataSource.slice(row, row + 1)[0], value);
  } else {
    dataRow[prop] = value;
  }
};

/**
 * This ridiculous piece of code maps rows Id that are present in table data to those displayed for user.
 * The trick is, the physical row id (stored in settings.data) is not necessary the same
 * as the visual (displayed) row id (e.g. when sorting is applied).
 *
 * @param {Number} index Visual row index.
 * @param {Number} amount
 * @fires Hooks#modifyRow
 * @returns {Number}
 */
DataMap.prototype.visualRowsToPhysical = function (index, amount) {
  var totalRows = this.instance.countSourceRows();
  var physicRow = (totalRows + index) % totalRows;
  var logicRows = [];
  var rowsToRemove = amount;
  var row;

  while (physicRow < totalRows && rowsToRemove) {
    row = this.instance.runHooks('modifyRow', physicRow);
    logicRows.push(row);

    rowsToRemove--;
    physicRow++;
  }

  return logicRows;
};

/**
 *
 * @param index Visual column index.
 * @param amount
 * @returns {Array}
 */
DataMap.prototype.visualColumnsToPhysical = function (index, amount) {
  var totalCols = this.instance.countCols();
  var physicalCol = (totalCols + index) % totalCols;
  var visualCols = [];
  var colsToRemove = amount;

  while (physicalCol < totalCols && colsToRemove) {
    var col = this.instance.runHooks('modifyCol', physicalCol);

    visualCols.push(col);

    colsToRemove--;
    physicalCol++;
  }

  return visualCols;
};

/**
 * Clears the data array.
 */
DataMap.prototype.clear = function () {
  for (var r = 0; r < this.instance.countSourceRows(); r++) {
    for (var c = 0; c < this.instance.countCols(); c++) {
      this.set(r, this.colToProp(c), '');
    }
  }
};

/**
 * Clear cached data length.
 */
DataMap.prototype.clearLengthCache = function () {
  this.cachedLength = null;
};

/**
 * Get data length.
 *
 * @returns {Number}
 */
DataMap.prototype.getLength = function () {
  var _this2 = this;

  var maxRows = void 0,
      maxRowsFromSettings = this.instance.getSettings().maxRows;

  if (maxRowsFromSettings < 0 || maxRowsFromSettings === 0) {
    maxRows = 0;
  } else {
    maxRows = maxRowsFromSettings || Infinity;
  }

  var length = this.instance.countSourceRows();

  if (this.instance.hasHook('modifyRow')) {
    var reValidate = this.skipCache;

    this.interval.start();
    if (length !== this.latestSourceRowsCount) {
      reValidate = true;
    }

    this.latestSourceRowsCount = length;
    if (this.cachedLength === null || reValidate) {
      (0, _number.rangeEach)(length - 1, function (row) {
        row = _this2.instance.runHooks('modifyRow', row);

        if (row === null) {
          --length;
        }
      });
      this.cachedLength = length;
    } else {
      length = this.cachedLength;
    }
  } else {
    this.interval.stop();
  }

  return Math.min(length, maxRows);
};

/**
 * Returns the data array.
 *
 * @returns {Array}
 */
DataMap.prototype.getAll = function () {
  var start = {
    row: 0,
    col: 0
  };

  var end = {
    row: Math.max(this.instance.countSourceRows() - 1, 0),
    col: Math.max(this.instance.countCols() - 1, 0)
  };

  if (start.row - end.row === 0 && !this.instance.countSourceRows()) {
    return [];
  }

  return this.getRange(start, end, DataMap.prototype.DESTINATION_RENDERER);
};

/**
 * Returns data range as array.
 *
 * @param {Object} [start] Start selection position. Visual indexes.
 * @param {Object} [end] End selection position. Visual indexes.
 * @param {Number} destination Destination of datamap.get
 * @returns {Array}
 */
DataMap.prototype.getRange = function (start, end, destination) {
  var r,
      rlen,
      c,
      clen,
      output = [],
      row;

  var maxRows = this.instance.getSettings().maxRows;
  var maxCols = this.instance.getSettings().maxCols;

  if (maxRows === 0 || maxCols === 0) {
    return [];
  }

  var getFn = destination === this.DESTINATION_CLIPBOARD_GENERATOR ? this.getCopyable : this.get;

  rlen = Math.min(Math.max(maxRows - 1, 0), Math.max(start.row, end.row));
  clen = Math.min(Math.max(maxCols - 1, 0), Math.max(start.col, end.col));

  for (r = Math.min(start.row, end.row); r <= rlen; r++) {
    row = [];
    var physicalRow = this.instance.runHooks('modifyRow', r);

    for (c = Math.min(start.col, end.col); c <= clen; c++) {

      if (physicalRow === null) {
        break;
      }
      row.push(getFn.call(this, r, this.colToProp(c)));
    }
    if (physicalRow !== null) {
      output.push(row);
    }
  }

  return output;
};

/**
 * Return data as text (tab separated columns).
 *
 * @param {Object} [start] Start selection position. Visual indexes.
 * @param {Object} [end] End selection position. Visual indexes.
 * @returns {String}
 */
DataMap.prototype.getText = function (start, end) {
  return _SheetClip2.default.stringify(this.getRange(start, end, this.DESTINATION_RENDERER));
};

/**
 * Return data as copyable text (tab separated columns intended for clipboard copy to an external application).
 *
 * @param {Object} [start] Start selection position. Visual indexes.
 * @param {Object} [end] End selection position. Visual indexes.
 * @returns {String}
 */
DataMap.prototype.getCopyableText = function (start, end) {
  return _SheetClip2.default.stringify(this.getRange(start, end, this.DESTINATION_CLIPBOARD_GENERATOR));
};

/**
 * `skipLengthCache` callback.
 * @private
 * @param {Number} delay Time of the delay in milliseconds.
 */
DataMap.prototype.onSkipLengthCache = function (delay) {
  var _this3 = this;

  this.skipCache = true;
  setTimeout(function () {
    _this3.skipCache = false;
  }, delay);
};

/**
 * Destroy instance.
 */
DataMap.prototype.destroy = function () {
  this.interval.stop();

  this.interval = null;
  this.instance = null;
  this.priv = null;
  this.GridSettings = null;
  this.dataSource = null;
  this.cachedLength = null;
  this.duckSchema = null;
};

exports.default = DataMap;

/***/ }),
/* 322 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


exports.__esModule = true;

var _createClass = 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); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

var _object = __webpack_require__(3);

var _array = __webpack_require__(2);

var _number = __webpack_require__(5);

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

/**
 * @class DataSource
 * @private
 */
var DataSource = function () {
  function DataSource(hotInstance) {
    var dataSource = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];

    _classCallCheck(this, DataSource);

    /**
     * Instance of Handsontable.
     *
     * @type {Handsontable}
     */
    this.hot = hotInstance;
    /**
     * Data source
     *
     * @type {Array}
     */
    this.data = dataSource;
    /**
     * Type of data source.
     *
     * @type {String}
     * @default 'array'
     */
    this.dataType = 'array';

    this.colToProp = function () {};
    this.propToCol = function () {};
  }

  /**
   * Get all data.
   *
   * @param {Boolean} [toArray=false] If `true` return source data as an array of arrays even when source data was provided
   *                                  in another format.
   * @returns {Array}
   */


  _createClass(DataSource, [{
    key: 'getData',
    value: function getData() {
      var toArray = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;

      var result = this.data;

      if (toArray) {
        result = this.getByRange({ row: 0, col: 0 }, { row: Math.max(this.countRows() - 1, 0), col: Math.max(this.countColumns() - 1, 0) }, true);
      }

      return result;
    }

    /**
     * Set new data source.
     *
     * @param data {Array}
     */

  }, {
    key: 'setData',
    value: function setData(data) {
      this.data = data;
    }

    /**
     * Returns array of column values from the data source. `column` is the index of the row in the data source.
     *
     * @param {Number} column Visual column index.
     * @returns {Array}
     */

  }, {
    key: 'getAtColumn',
    value: function getAtColumn(column) {
      var _this = this;

      var result = [];

      (0, _array.arrayEach)(this.data, function (row) {
        var property = _this.colToProp(column);

        if (typeof property === 'string') {
          row = (0, _object.getProperty)(row, property);
        } else {
          row = row[property];
        }
        result.push(row);
      });

      return result;
    }

    /**
     * Returns a single row of the data (array or object, depending on what you have). `row` is the index of the row in the data source.
     *
     * @param {Number} row Physical row index.
     * @returns {Array|Object}
     */

  }, {
    key: 'getAtRow',
    value: function getAtRow(row) {
      return this.data[row];
    }

    /**
     * Returns a single value from the data.
     *
     * @param {Number} row Physical row index.
     * @param {Number} column Visual column index.
     * @returns {*}
     */

  }, {
    key: 'getAtCell',
    value: function getAtCell(row, column) {
      var result = null;

      var modifyRowData = this.hot.runHooks('modifyRowData', row);

      var dataRow = isNaN(modifyRowData) ? modifyRowData : this.data[row];

      if (dataRow) {
        var prop = this.colToProp(column);

        if (typeof prop === 'string') {
          result = (0, _object.getProperty)(dataRow, prop);
        } else if (typeof prop === 'function') {
          result = prop(this.data.slice(row, row + 1)[0]);
        } else {
          result = dataRow[prop];
        }
      }

      return result;
    }

    /**
     * Returns source data by passed range.
     *
     * @param {Object} start Object with physical `row` and `col` keys (or visual column index, if data type is an array of objects).
     * @param {Object} end Object with physical `row` and `col` keys (or visual column index, if data type is an array of objects).
     * @param {Boolean} [toArray=false] If `true` return source data as an array of arrays even when source data was provided
     *                                  in another format.
     * @returns {Array}
     */

  }, {
    key: 'getByRange',
    value: function getByRange(start, end) {
      var _this2 = this;

      var toArray = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;

      var startRow = Math.min(start.row, end.row);
      var startCol = Math.min(start.col, end.col);
      var endRow = Math.max(start.row, end.row);
      var endCol = Math.max(start.col, end.col);
      var result = [];

      (0, _number.rangeEach)(startRow, endRow, function (currentRow) {
        var row = _this2.getAtRow(currentRow);
        var newRow = void 0;

        if (_this2.dataType === 'array') {
          newRow = row.slice(startCol, endCol + 1);
        } else if (_this2.dataType === 'object') {
          newRow = toArray ? [] : {};

          (0, _number.rangeEach)(startCol, endCol, function (column) {
            var prop = _this2.colToProp(column);

            if (toArray) {
              newRow.push(row[prop]);
            } else {
              newRow[prop] = row[prop];
            }
          });
        }

        result.push(newRow);
      });

      return result;
    }

    /**
     * Count number of rows.
     *
     * @returns {Number}
     */

  }, {
    key: 'countRows',
    value: function countRows() {
      return Array.isArray(this.data) ? this.data.length : 0;
    }

    /**
     * Count number of columns.
     *
     * @returns {Number}
     */

  }, {
    key: 'countColumns',
    value: function countColumns() {
      var result = 0;

      if (Array.isArray(this.data)) {
        if (this.dataType === 'array') {
          result = this.data[0].length;
        } else if (this.dataType === 'object') {
          result = Object.keys(this.data[0]).length;
        }
      }

      return result;
    }

    /**
     * Destroy instance.
     */

  }, {
    key: 'destroy',
    value: function destroy() {
      this.data = null;
      this.hot = null;
    }
  }]);

  return DataSource;
}();

exports.default = DataSource;

/***/ }),
/* 323 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


exports.__esModule = true;

var _src = __webpack_require__(14);

var _unicode = __webpack_require__(15);

var _event = __webpack_require__(7);

var _editors = __webpack_require__(13);

var _eventManager = __webpack_require__(4);

var _eventManager2 = _interopRequireDefault(_eventManager);

var _baseEditor = __webpack_require__(36);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

function EditorManager(instance, priv, selection) {
  var _this = this,
      destroyed = false,
      eventManager,
      activeEditor;

  eventManager = new _eventManager2.default(instance);

  function moveSelectionAfterEnter(shiftKey) {
    selection.setSelectedHeaders(false, false, false);
    var enterMoves = typeof priv.settings.enterMoves === 'function' ? priv.settings.enterMoves(event) : priv.settings.enterMoves;

    if (shiftKey) {
      // move selection up
      selection.transformStart(-enterMoves.row, -enterMoves.col);
    } else {
      // move selection down (add a new row if needed)
      selection.transformStart(enterMoves.row, enterMoves.col, true);
    }
  }

  function moveSelectionUp(shiftKey) {
    if (shiftKey) {
      if (selection.selectedHeader.cols) {
        selection.setSelectedHeaders(selection.selectedHeader.rows, false, false);
      }
      selection.transformEnd(-1, 0);
    } else {
      selection.setSelectedHeaders(false, false, false);
      selection.transformStart(-1, 0);
    }
  }

  function moveSelectionDown(shiftKey) {
    if (shiftKey) {
      // expanding selection down with shift
      selection.transformEnd(1, 0);
    } else {
      selection.setSelectedHeaders(false, false, false);
      selection.transformStart(1, 0);
    }
  }

  function moveSelectionRight(shiftKey) {
    if (shiftKey) {
      selection.transformEnd(0, 1);
    } else {
      selection.setSelectedHeaders(false, false, false);
      selection.transformStart(0, 1);
    }
  }

  function moveSelectionLeft(shiftKey) {
    if (shiftKey) {
      if (selection.selectedHeader.rows) {
        selection.setSelectedHeaders(false, selection.selectedHeader.cols, false);
      }
      selection.transformEnd(0, -1);
    } else {
      selection.setSelectedHeaders(false, false, false);
      selection.transformStart(0, -1);
    }
  }

  function onKeyDown(event) {
    var ctrlDown, rangeModifier;

    if (!instance.isListening()) {
      return;
    }
    instance.runHooks('beforeKeyDown', event);

    if (destroyed) {
      return;
    }
    if ((0, _event.isImmediatePropagationStopped)(event)) {
      return;
    }
    priv.lastKeyCode = event.keyCode;

    if (!selection.isSelected()) {
      return;
    }
    // catch CTRL but not right ALT (which in some systems triggers ALT+CTRL)
    ctrlDown = (event.ctrlKey || event.metaKey) && !event.altKey;

    if (activeEditor && !activeEditor.isWaiting()) {
      if (!(0, _unicode.isMetaKey)(event.keyCode) && !(0, _unicode.isCtrlKey)(event.keyCode) && !ctrlDown && !_this.isEditorOpened()) {
        _this.openEditor('', event);

        return;
      }
    }
    rangeModifier = event.shiftKey ? selection.setRangeEnd : selection.setRangeStart;

    switch (event.keyCode) {
      case _unicode.KEY_CODES.A:
        if (!_this.isEditorOpened() && ctrlDown) {
          selection.selectAll();

          event.preventDefault();
          (0, _event.stopPropagation)(event);
        }
        break;

      case _unicode.KEY_CODES.ARROW_UP:
        if (_this.isEditorOpened() && !activeEditor.isWaiting()) {
          _this.closeEditorAndSaveChanges(ctrlDown);
        }
        moveSelectionUp(event.shiftKey);

        event.preventDefault();
        (0, _event.stopPropagation)(event);
        break;

      case _unicode.KEY_CODES.ARROW_DOWN:
        if (_this.isEditorOpened() && !activeEditor.isWaiting()) {
          _this.closeEditorAndSaveChanges(ctrlDown);
        }

        moveSelectionDown(event.shiftKey);

        event.preventDefault();
        (0, _event.stopPropagation)(event);
        break;

      case _unicode.KEY_CODES.ARROW_RIGHT:
        if (_this.isEditorOpened() && !activeEditor.isWaiting()) {
          _this.closeEditorAndSaveChanges(ctrlDown);
        }

        moveSelectionRight(event.shiftKey);

        event.preventDefault();
        (0, _event.stopPropagation)(event);
        break;

      case _unicode.KEY_CODES.ARROW_LEFT:
        if (_this.isEditorOpened() && !activeEditor.isWaiting()) {
          _this.closeEditorAndSaveChanges(ctrlDown);
        }

        moveSelectionLeft(event.shiftKey);

        event.preventDefault();
        (0, _event.stopPropagation)(event);
        break;

      case _unicode.KEY_CODES.TAB:
        selection.setSelectedHeaders(false, false, false);
        var tabMoves = typeof priv.settings.tabMoves === 'function' ? priv.settings.tabMoves(event) : priv.settings.tabMoves;

        if (event.shiftKey) {
          // move selection left
          selection.transformStart(-tabMoves.row, -tabMoves.col);
        } else {
          // move selection right (add a new column if needed)
          selection.transformStart(tabMoves.row, tabMoves.col, true);
        }
        event.preventDefault();
        (0, _event.stopPropagation)(event);
        break;

      case _unicode.KEY_CODES.BACKSPACE:
      case _unicode.KEY_CODES.DELETE:
        selection.empty(event);
        _this.prepareEditor();
        event.preventDefault();
        break;

      case _unicode.KEY_CODES.F2:
        /* F2 */
        _this.openEditor(null, event);

        if (activeEditor) {
          activeEditor.enableFullEditMode();
        }
        event.preventDefault(); // prevent Opera from opening 'Go to Page dialog'
        break;

      case _unicode.KEY_CODES.ENTER:
        /* return/enter */
        if (_this.isEditorOpened()) {

          if (activeEditor && activeEditor.state !== _baseEditor.EditorState.WAITING) {
            _this.closeEditorAndSaveChanges(ctrlDown);
          }
          moveSelectionAfterEnter(event.shiftKey);
        } else if (instance.getSettings().enterBeginsEditing) {
          _this.openEditor(null, event);

          if (activeEditor) {
            activeEditor.enableFullEditMode();
          }
        } else {
          moveSelectionAfterEnter(event.shiftKey);
        }
        event.preventDefault(); // don't add newline to field
        (0, _event.stopImmediatePropagation)(event); // required by HandsontableEditor
        break;

      case _unicode.KEY_CODES.ESCAPE:
        if (_this.isEditorOpened()) {
          _this.closeEditorAndRestoreOriginalValue(ctrlDown);
        }
        event.preventDefault();
        break;

      case _unicode.KEY_CODES.HOME:
        selection.setSelectedHeaders(false, false, false);
        if (event.ctrlKey || event.metaKey) {
          rangeModifier(new _src.CellCoords(0, priv.selRange.from.col));
        } else {
          rangeModifier(new _src.CellCoords(priv.selRange.from.row, 0));
        }
        event.preventDefault(); // don't scroll the window
        (0, _event.stopPropagation)(event);
        break;

      case _unicode.KEY_CODES.END:
        selection.setSelectedHeaders(false, false, false);
        if (event.ctrlKey || event.metaKey) {
          rangeModifier(new _src.CellCoords(instance.countRows() - 1, priv.selRange.from.col));
        } else {
          rangeModifier(new _src.CellCoords(priv.selRange.from.row, instance.countCols() - 1));
        }
        event.preventDefault(); // don't scroll the window
        (0, _event.stopPropagation)(event);
        break;

      case _unicode.KEY_CODES.PAGE_UP:
        selection.setSelectedHeaders(false, false, false);
        selection.transformStart(-instance.countVisibleRows(), 0);
        event.preventDefault(); // don't page up the window
        (0, _event.stopPropagation)(event);
        break;

      case _unicode.KEY_CODES.PAGE_DOWN:
        selection.setSelectedHeaders(false, false, false);
        selection.transformStart(instance.countVisibleRows(), 0);
        event.preventDefault(); // don't page down the window
        (0, _event.stopPropagation)(event);
        break;
      default:
        break;
    }
  }

  function init() {
    instance.addHook('afterDocumentKeyDown', onKeyDown);

    eventManager.addEventListener(document.documentElement, 'keydown', function (event) {
      if (!destroyed) {
        instance.runHooks('afterDocumentKeyDown', event);
      }
    });

    function onDblClick(event, coords, elem) {
      // may be TD or TH
      if (elem.nodeName == 'TD') {
        _this.openEditor();

        if (activeEditor) {
          activeEditor.enableFullEditMode();
        }
      }
    }
    instance.view.wt.update('onCellDblClick', onDblClick);

    instance.addHook('afterDestroy', function () {
      destroyed = true;
    });
  }

  /**
   * Destroy current editor, if exists.
   *
   * @function destroyEditor
   * @memberof! Handsontable.EditorManager#
   * @param {Boolean} revertOriginal
   */
  this.destroyEditor = function (revertOriginal) {
    this.closeEditor(revertOriginal);
  };

  /**
   * Get active editor.
   *
   * @function getActiveEditor
   * @memberof! Handsontable.EditorManager#
   * @returns {*}
   */
  this.getActiveEditor = function () {
    return activeEditor;
  };

  /**
   * Prepare text input to be displayed at given grid cell.
   *
   * @function prepareEditor
   * @memberof! Handsontable.EditorManager#
   */
  this.prepareEditor = function () {
    var row, col, prop, td, originalValue, cellProperties, editorClass;

    if (activeEditor && activeEditor.isWaiting()) {
      this.closeEditor(false, false, function (dataSaved) {
        if (dataSaved) {
          _this.prepareEditor();
        }
      });

      return;
    }
    row = priv.selRange.highlight.row;
    col = priv.selRange.highlight.col;
    prop = instance.colToProp(col);
    td = instance.getCell(row, col);

    originalValue = instance.getSourceDataAtCell(instance.runHooks('modifyRow', row), col);
    cellProperties = instance.getCellMeta(row, col);
    editorClass = instance.getCellEditor(cellProperties);

    if (editorClass) {
      activeEditor = (0, _editors.getEditorInstance)(editorClass, instance);
      activeEditor.prepare(row, col, prop, td, originalValue, cellProperties);
    } else {
      activeEditor = void 0;
    }
  };

  /**
   * Check is editor is opened/showed.
   *
   * @function isEditorOpened
   * @memberof! Handsontable.EditorManager#
   * @returns {Boolean}
   */
  this.isEditorOpened = function () {
    return activeEditor && activeEditor.isOpened();
  };

  /**
   * Open editor with initial value.
   *
   * @function openEditor
   * @memberof! Handsontable.EditorManager#
   * @param {String} initialValue
   * @param {DOMEvent} event
   */
  this.openEditor = function (initialValue, event) {
    if (activeEditor && !activeEditor.cellProperties.readOnly) {
      activeEditor.beginEditing(initialValue, event);
    } else if (activeEditor && activeEditor.cellProperties.readOnly) {

      // move the selection after opening the editor with ENTER key
      if (event && event.keyCode === _unicode.KEY_CODES.ENTER) {
        moveSelectionAfterEnter();
      }
    }
  };

  /**
   * Close editor, finish editing cell.
   *
   * @function closeEditor
   * @memberof! Handsontable.EditorManager#
   * @param {Boolean} restoreOriginalValue
   * @param {Boolean} [ctrlDown]
   * @param {Function} [callback]
   */
  this.closeEditor = function (restoreOriginalValue, ctrlDown, callback) {
    if (activeEditor) {
      activeEditor.finishEditing(restoreOriginalValue, ctrlDown, callback);
    } else if (callback) {
      callback(false);
    }
  };

  /**
   * Close editor and save changes.
   *
   * @function closeEditorAndSaveChanges
   * @memberof! Handsontable.EditorManager#
   * @param {Boolean} ctrlDown
   */
  this.closeEditorAndSaveChanges = function (ctrlDown) {
    return this.closeEditor(false, ctrlDown);
  };

  /**
   * Close editor and restore original value.
   *
   * @function closeEditorAndRestoreOriginalValue
   * @memberof! Handsontable.EditorManager#
   * @param {Boolean} ctrlDown
   */
  this.closeEditorAndRestoreOriginalValue = function (ctrlDown) {
    return this.closeEditor(true, ctrlDown);
  };

  init();
}

exports.default = EditorManager;

/***/ }),
/* 324 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


exports.__esModule = true;

var _createClass = 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); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

var _baseEditor = __webpack_require__(36);

var _baseEditor2 = _interopRequireDefault(_baseEditor);

var _element = __webpack_require__(0);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }

function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }

/**
 * @private
 * @editor CheckboxEditor
 * @class CheckboxEditor
 */
var CheckboxEditor = function (_BaseEditor) {
  _inherits(CheckboxEditor, _BaseEditor);

  function CheckboxEditor() {
    _classCallCheck(this, CheckboxEditor);

    return _possibleConstructorReturn(this, (CheckboxEditor.__proto__ || Object.getPrototypeOf(CheckboxEditor)).apply(this, arguments));
  }

  _createClass(CheckboxEditor, [{
    key: 'beginEditing',
    value: function beginEditing(initialValue, event) {
      // editorManager return double click event as undefined
      if (event === void 0) {
        var checkbox = this.TD.querySelector('input[type="checkbox"]');

        if (!(0, _element.hasClass)(checkbox, 'htBadValue')) {
          checkbox.click();
        }
      }
    }
  }, {
    key: 'finishEditing',
    value: function finishEditing() {}
  }, {
    key: 'init',
    value: function init() {}
  }, {
    key: 'open',
    value: function open() {}
  }, {
    key: 'close',
    value: function close() {}
  }, {
    key: 'getValue',
    value: function getValue() {}
  }, {
    key: 'setValue',
    value: function setValue() {}
  }, {
    key: 'focus',
    value: function focus() {}
  }]);

  return CheckboxEditor;
}(_baseEditor2.default);

exports.default = CheckboxEditor;

/***/ }),
/* 325 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


exports.__esModule = true;

var _createClass = 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); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

var _get = function get(object, property, receiver) { if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ("value" in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } };

var _moment = __webpack_require__(42);

var _moment2 = _interopRequireDefault(_moment);

var _pikaday = __webpack_require__(410);

var _pikaday2 = _interopRequireDefault(_pikaday);

__webpack_require__(298);

var _element = __webpack_require__(0);

var _object = __webpack_require__(3);

var _eventManager = __webpack_require__(4);

var _eventManager2 = _interopRequireDefault(_eventManager);

var _unicode = __webpack_require__(15);

var _event = __webpack_require__(7);

var _textEditor = __webpack_require__(44);

var _textEditor2 = _interopRequireDefault(_textEditor);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }

function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }

/**
 * @private
 * @editor DateEditor
 * @class DateEditor
 * @dependencies TextEditor moment pikaday
 */
var DateEditor = function (_TextEditor) {
  _inherits(DateEditor, _TextEditor);

  /**
   * @param {Core} hotInstance Handsontable instance
   * @private
   */
  function DateEditor(hotInstance) {
    _classCallCheck(this, DateEditor);

    // TODO: Move this option to general settings
    var _this = _possibleConstructorReturn(this, (DateEditor.__proto__ || Object.getPrototypeOf(DateEditor)).call(this, hotInstance));

    _this.defaultDateFormat = 'DD/MM/YYYY';
    _this.isCellEdited = false;
    _this.parentDestroyed = false;
    return _this;
  }

  _createClass(DateEditor, [{
    key: 'init',
    value: function init() {
      var _this2 = this;

      if (typeof _moment2.default !== 'function') {
        throw new Error('You need to include moment.js to your project.');
      }

      if (typeof _pikaday2.default !== 'function') {
        throw new Error('You need to include Pikaday to your project.');
      }
      _get(DateEditor.prototype.__proto__ || Object.getPrototypeOf(DateEditor.prototype), 'init', this).call(this);
      this.instance.addHook('afterDestroy', function () {
        _this2.parentDestroyed = true;
        _this2.destroyElements();
      });
    }

    /**
     * Create data picker instance
     */

  }, {
    key: 'createElements',
    value: function createElements() {
      _get(DateEditor.prototype.__proto__ || Object.getPrototypeOf(DateEditor.prototype), 'createElements', this).call(this);

      this.datePicker = document.createElement('DIV');
      this.datePickerStyle = this.datePicker.style;
      this.datePickerStyle.position = 'absolute';
      this.datePickerStyle.top = 0;
      this.datePickerStyle.left = 0;
      this.datePickerStyle.zIndex = 9999;

      (0, _element.addClass)(this.datePicker, 'htDatepickerHolder');
      document.body.appendChild(this.datePicker);

      this.$datePicker = new _pikaday2.default(this.getDatePickerConfig());
      var eventManager = new _eventManager2.default(this);

      /**
       * Prevent recognizing clicking on datepicker as clicking outside of table
       */
      eventManager.addEventListener(this.datePicker, 'mousedown', function (event) {
        return (0, _event.stopPropagation)(event);
      });
      this.hideDatepicker();
    }

    /**
     * Destroy data picker instance
     */

  }, {
    key: 'destroyElements',
    value: function destroyElements() {
      this.$datePicker.destroy();
    }

    /**
     * Prepare editor to appear
     *
     * @param {Number} row Row index
     * @param {Number} col Column index
     * @param {String} prop Property name (passed when datasource is an array of objects)
     * @param {HTMLTableCellElement} td Table cell element
     * @param {*} originalValue Original value
     * @param {Object} cellProperties Object with cell properties ({@see Core#getCellMeta})
     */

  }, {
    key: 'prepare',
    value: function prepare(row, col, prop, td, originalValue, cellProperties) {
      this._opened = false;
      _get(DateEditor.prototype.__proto__ || Object.getPrototypeOf(DateEditor.prototype), 'prepare', this).call(this, row, col, prop, td, originalValue, cellProperties);
    }

    /**
     * Open editor
     *
     * @param {Event} [event=null]
     */

  }, {
    key: 'open',
    value: function open() {
      var event = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;

      _get(DateEditor.prototype.__proto__ || Object.getPrototypeOf(DateEditor.prototype), 'open', this).call(this);
      this.showDatepicker(event);
    }

    /**
     * Close editor
     */

  }, {
    key: 'close',
    value: function close() {
      var _this3 = this;

      this._opened = false;
      this.instance._registerTimeout(setTimeout(function () {
        _this3.instance.selection.refreshBorders();
      }, 0));

      _get(DateEditor.prototype.__proto__ || Object.getPrototypeOf(DateEditor.prototype), 'close', this).call(this);
    }

    /**
     * @param {Boolean} [isCancelled=false]
     * @param {Boolean} [ctrlDown=false]
     */

  }, {
    key: 'finishEditing',
    value: function finishEditing() {
      var isCancelled = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
      var ctrlDown = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;

      if (isCancelled) {
        // pressed ESC, restore original value
        // var value = this.instance.getDataAtCell(this.row, this.col);
        var value = this.originalValue;

        if (value !== void 0) {
          this.setValue(value);
        }
      }
      this.hideDatepicker();
      _get(DateEditor.prototype.__proto__ || Object.getPrototypeOf(DateEditor.prototype), 'finishEditing', this).call(this, isCancelled, ctrlDown);
    }

    /**
     * Show data picker
     *
     * @param {Event} event
     */

  }, {
    key: 'showDatepicker',
    value: function showDatepicker(event) {
      this.$datePicker.config(this.getDatePickerConfig());

      var offset = this.TD.getBoundingClientRect();
      var dateFormat = this.cellProperties.dateFormat || this.defaultDateFormat;
      var datePickerConfig = this.$datePicker.config();
      var dateStr = void 0;
      var isMouseDown = this.instance.view.isMouseDown();
      var isMeta = event ? (0, _unicode.isMetaKey)(event.keyCode) : false;

      this.datePickerStyle.top = window.pageYOffset + offset.top + (0, _element.outerHeight)(this.TD) + 'px';
      this.datePickerStyle.left = window.pageXOffset + offset.left + 'px';

      this.$datePicker._onInputFocus = function () {};
      datePickerConfig.format = dateFormat;

      if (this.originalValue) {
        dateStr = this.originalValue;

        if ((0, _moment2.default)(dateStr, dateFormat, true).isValid()) {
          this.$datePicker.setMoment((0, _moment2.default)(dateStr, dateFormat), true);
        }

        // workaround for date/time cells - pikaday resets the cell value to 12:00 AM by default, this will overwrite the value.
        if (this.getValue() !== this.originalValue) {
          this.setValue(this.originalValue);
        }

        if (!isMeta && !isMouseDown) {
          this.setValue('');
        }
      } else if (this.cellProperties.defaultDate) {
        dateStr = this.cellProperties.defaultDate;

        datePickerConfig.defaultDate = dateStr;

        if ((0, _moment2.default)(dateStr, dateFormat, true).isValid()) {
          this.$datePicker.setMoment((0, _moment2.default)(dateStr, dateFormat), true);
        }

        if (!isMeta && !isMouseDown) {
          this.setValue('');
        }
      } else {
        // if a default date is not defined, set a soft-default-date: display the current day and month in the
        // datepicker, but don't fill the editor input
        this.$datePicker.gotoToday();
      }

      this.datePickerStyle.display = 'block';
      this.$datePicker.show();
    }

    /**
     * Hide data picker
     */

  }, {
    key: 'hideDatepicker',
    value: function hideDatepicker() {
      this.datePickerStyle.display = 'none';
      this.$datePicker.hide();
    }

    /**
     * Get date picker options.
     *
     * @returns {Object}
     */

  }, {
    key: 'getDatePickerConfig',
    value: function getDatePickerConfig() {
      var _this4 = this;

      var htInput = this.TEXTAREA;
      var options = {};

      if (this.cellProperties && this.cellProperties.datePickerConfig) {
        (0, _object.deepExtend)(options, this.cellProperties.datePickerConfig);
      }
      var origOnSelect = options.onSelect;
      var origOnClose = options.onClose;

      options.field = htInput;
      options.trigger = htInput;
      options.container = this.datePicker;
      options.bound = false;
      options.format = options.format || this.defaultDateFormat;
      options.reposition = options.reposition || false;
      options.onSelect = function (dateStr) {
        if (!isNaN(dateStr.getTime())) {
          dateStr = (0, _moment2.default)(dateStr).format(_this4.cellProperties.dateFormat || _this4.defaultDateFormat);
        }
        _this4.setValue(dateStr);
        _this4.hideDatepicker();

        if (origOnSelect) {
          origOnSelect();
        }
      };
      options.onClose = function () {
        if (!_this4.parentDestroyed) {
          _this4.finishEditing(false);
        }
        if (origOnClose) {
          origOnClose();
        }
      };

      return options;
    }
  }]);

  return DateEditor;
}(_textEditor2.default);

exports.default = DateEditor;

/***/ }),
/* 326 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


exports.__esModule = true;

var _createClass = 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); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

var _get = function get(object, property, receiver) { if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ("value" in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } };

var _autocompleteEditor = __webpack_require__(263);

var _autocompleteEditor2 = _interopRequireDefault(_autocompleteEditor);

var _pluginHooks = __webpack_require__(11);

var _pluginHooks2 = _interopRequireDefault(_pluginHooks);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }

function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }

/**
 * @private
 * @editor DropdownEditor
 * @class DropdownEditor
 * @dependencies AutocompleteEditor
 */
var DropdownEditor = function (_AutocompleteEditor) {
  _inherits(DropdownEditor, _AutocompleteEditor);

  function DropdownEditor() {
    _classCallCheck(this, DropdownEditor);

    return _possibleConstructorReturn(this, (DropdownEditor.__proto__ || Object.getPrototypeOf(DropdownEditor)).apply(this, arguments));
  }

  _createClass(DropdownEditor, [{
    key: 'prepare',
    value: function prepare(row, col, prop, td, originalValue, cellProperties) {
      _get(DropdownEditor.prototype.__proto__ || Object.getPrototypeOf(DropdownEditor.prototype), 'prepare', this).call(this, row, col, prop, td, originalValue, cellProperties);
      this.cellProperties.filter = false;
      this.cellProperties.strict = true;
    }
  }]);

  return DropdownEditor;
}(_autocompleteEditor2.default);

_pluginHooks2.default.getSingleton().add('beforeValidate', function (value, row, col, source) {
  var cellMeta = this.getCellMeta(row, this.propToCol(col));

  if (cellMeta.editor === DropdownEditor) {
    if (cellMeta.strict === void 0) {
      cellMeta.filter = false;
      cellMeta.strict = true;
    }
  }
});

exports.default = DropdownEditor;

/***/ }),
/* 327 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


exports.__esModule = true;

var _unicode = __webpack_require__(15);

var _event = __webpack_require__(7);

var _element = __webpack_require__(0);

var _baseEditor = __webpack_require__(36);

var _baseEditor2 = _interopRequireDefault(_baseEditor);

var _eventManager = __webpack_require__(4);

var _eventManager2 = _interopRequireDefault(_eventManager);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

var MobileTextEditor = _baseEditor2.default.prototype.extend();
var domDimensionsCache = {};

/**
 * @private
 * @editor MobileTextEditor
 * @class MobileTextEditor
 */
var createControls = function createControls() {
  this.controls = {};

  this.controls.leftButton = document.createElement('DIV');
  this.controls.leftButton.className = 'leftButton';
  this.controls.rightButton = document.createElement('DIV');
  this.controls.rightButton.className = 'rightButton';
  this.controls.upButton = document.createElement('DIV');
  this.controls.upButton.className = 'upButton';
  this.controls.downButton = document.createElement('DIV');
  this.controls.downButton.className = 'downButton';

  for (var button in this.controls) {
    if (Object.prototype.hasOwnProperty.call(this.controls, button)) {
      this.positionControls.appendChild(this.controls[button]);
    }
  }
};

MobileTextEditor.prototype.valueChanged = function () {
  return this.initValue != this.getValue();
};

MobileTextEditor.prototype.init = function () {
  var that = this;
  this.eventManager = new _eventManager2.default(this.instance);

  this.createElements();
  this.bindEvents();

  this.instance.addHook('afterDestroy', function () {
    that.destroy();
  });
};

MobileTextEditor.prototype.getValue = function () {
  return this.TEXTAREA.value;
};

MobileTextEditor.prototype.setValue = function (newValue) {
  this.initValue = newValue;

  this.TEXTAREA.value = newValue;
};

MobileTextEditor.prototype.createElements = function () {
  this.editorContainer = document.createElement('DIV');
  this.editorContainer.className = 'htMobileEditorContainer';

  this.cellPointer = document.createElement('DIV');
  this.cellPointer.className = 'cellPointer';

  this.moveHandle = document.createElement('DIV');
  this.moveHandle.className = 'moveHandle';

  this.inputPane = document.createElement('DIV');
  this.inputPane.className = 'inputs';

  this.positionControls = document.createElement('DIV');
  this.positionControls.className = 'positionControls';

  this.TEXTAREA = document.createElement('TEXTAREA');
  (0, _element.addClass)(this.TEXTAREA, 'handsontableInput');

  this.inputPane.appendChild(this.TEXTAREA);

  this.editorContainer.appendChild(this.cellPointer);
  this.editorContainer.appendChild(this.moveHandle);
  this.editorContainer.appendChild(this.inputPane);
  this.editorContainer.appendChild(this.positionControls);

  createControls.call(this);

  document.body.appendChild(this.editorContainer);
};

MobileTextEditor.prototype.onBeforeKeyDown = function (event) {
  var instance = this;
  var that = instance.getActiveEditor();

  if (event.target !== that.TEXTAREA || (0, _event.isImmediatePropagationStopped)(event)) {
    return;
  }

  switch (event.keyCode) {
    case _unicode.KEY_CODES.ENTER:
      that.close();
      event.preventDefault(); // don't add newline to field
      break;
    case _unicode.KEY_CODES.BACKSPACE:
      (0, _event.stopImmediatePropagation)(event); // backspace, delete, home, end should only work locally when cell is edited (not in table context)
      break;
    default:
      break;
  }
};

MobileTextEditor.prototype.open = function () {
  this.instance.addHook('beforeKeyDown', this.onBeforeKeyDown);

  (0, _element.addClass)(this.editorContainer, 'active');
  (0, _element.removeClass)(this.cellPointer, 'hidden');

  this.updateEditorPosition();
};

MobileTextEditor.prototype.focus = function () {
  this.TEXTAREA.focus();
  (0, _element.setCaretPosition)(this.TEXTAREA, this.TEXTAREA.value.length);
};

MobileTextEditor.prototype.close = function () {
  this.TEXTAREA.blur();
  this.instance.removeHook('beforeKeyDown', this.onBeforeKeyDown);

  (0, _element.removeClass)(this.editorContainer, 'active');
};

MobileTextEditor.prototype.scrollToView = function () {
  var coords = this.instance.getSelectedRange().highlight;
  this.instance.view.scrollViewport(coords);
};

MobileTextEditor.prototype.hideCellPointer = function () {
  if (!(0, _element.hasClass)(this.cellPointer, 'hidden')) {
    (0, _element.addClass)(this.cellPointer, 'hidden');
  }
};

MobileTextEditor.prototype.updateEditorPosition = function (x, y) {
  if (x && y) {
    x = parseInt(x, 10);
    y = parseInt(y, 10);

    this.editorContainer.style.top = y + 'px';
    this.editorContainer.style.left = x + 'px';
  } else {
    var selection = this.instance.getSelected(),
        selectedCell = this.instance.getCell(selection[0], selection[1]);

    // cache sizes
    if (!domDimensionsCache.cellPointer) {
      domDimensionsCache.cellPointer = {
        height: (0, _element.outerHeight)(this.cellPointer),
        width: (0, _element.outerWidth)(this.cellPointer)
      };
    }
    if (!domDimensionsCache.editorContainer) {
      domDimensionsCache.editorContainer = {
        width: (0, _element.outerWidth)(this.editorContainer)
      };
    }

    if (selectedCell !== undefined) {
      var scrollLeft = this.instance.view.wt.wtOverlays.leftOverlay.trimmingContainer == window ? 0 : (0, _element.getScrollLeft)(this.instance.view.wt.wtOverlays.leftOverlay.holder);
      var scrollTop = this.instance.view.wt.wtOverlays.topOverlay.trimmingContainer == window ? 0 : (0, _element.getScrollTop)(this.instance.view.wt.wtOverlays.topOverlay.holder);

      var selectedCellOffset = (0, _element.offset)(selectedCell),
          selectedCellWidth = (0, _element.outerWidth)(selectedCell),
          currentScrollPosition = {
        x: scrollLeft,
        y: scrollTop
      };

      this.editorContainer.style.top = parseInt(selectedCellOffset.top + (0, _element.outerHeight)(selectedCell) - currentScrollPosition.y + domDimensionsCache.cellPointer.height, 10) + 'px';
      this.editorContainer.style.left = parseInt(window.innerWidth / 2 - domDimensionsCache.editorContainer.width / 2, 10) + 'px';

      if (selectedCellOffset.left + selectedCellWidth / 2 > parseInt(this.editorContainer.style.left, 10) + domDimensionsCache.editorContainer.width) {
        this.editorContainer.style.left = window.innerWidth - domDimensionsCache.editorContainer.width + 'px';
      } else if (selectedCellOffset.left + selectedCellWidth / 2 < parseInt(this.editorContainer.style.left, 10) + 20) {
        this.editorContainer.style.left = 0 + 'px';
      }

      this.cellPointer.style.left = parseInt(selectedCellOffset.left - domDimensionsCache.cellPointer.width / 2 - (0, _element.offset)(this.editorContainer).left + selectedCellWidth / 2 - currentScrollPosition.x, 10) + 'px';
    }
  }
};

MobileTextEditor.prototype.updateEditorData = function () {
  var selected = this.instance.getSelected(),
      selectedValue = this.instance.getDataAtCell(selected[0], selected[1]);

  this.row = selected[0];
  this.col = selected[1];
  this.setValue(selectedValue);
  this.updateEditorPosition();
};

MobileTextEditor.prototype.prepareAndSave = function () {
  var val;

  if (!this.valueChanged()) {
    return;
  }

  if (this.instance.getSettings().trimWhitespace) {
    val = [[String.prototype.trim.call(this.getValue())]];
  } else {
    val = [[this.getValue()]];
  }

  this.saveValue(val);
};

MobileTextEditor.prototype.bindEvents = function () {
  var that = this;

  this.eventManager.addEventListener(this.controls.leftButton, 'touchend', function (event) {
    that.prepareAndSave();
    that.instance.selection.transformStart(0, -1, null, true);
    that.updateEditorData();
    event.preventDefault();
  });
  this.eventManager.addEventListener(this.controls.rightButton, 'touchend', function (event) {
    that.prepareAndSave();
    that.instance.selection.transformStart(0, 1, null, true);
    that.updateEditorData();
    event.preventDefault();
  });
  this.eventManager.addEventListener(this.controls.upButton, 'touchend', function (event) {
    that.prepareAndSave();
    that.instance.selection.transformStart(-1, 0, null, true);
    that.updateEditorData();
    event.preventDefault();
  });
  this.eventManager.addEventListener(this.controls.downButton, 'touchend', function (event) {
    that.prepareAndSave();
    that.instance.selection.transformStart(1, 0, null, true);
    that.updateEditorData();
    event.preventDefault();
  });

  this.eventManager.addEventListener(this.moveHandle, 'touchstart', function (event) {
    if (event.touches.length == 1) {
      var touch = event.touches[0];
      var onTouchPosition = {
        x: that.editorContainer.offsetLeft,
        y: that.editorContainer.offsetTop
      };
      var onTouchOffset = {
        x: touch.pageX - onTouchPosition.x,
        y: touch.pageY - onTouchPosition.y
      };

      that.eventManager.addEventListener(this, 'touchmove', function (event) {
        var touch = event.touches[0];
        that.updateEditorPosition(touch.pageX - onTouchOffset.x, touch.pageY - onTouchOffset.y);
        that.hideCellPointer();
        event.preventDefault();
      });
    }
  });

  this.eventManager.addEventListener(document.body, 'touchend', function (event) {
    if (!(0, _element.isChildOf)(event.target, that.editorContainer) && !(0, _element.isChildOf)(event.target, that.instance.rootElement)) {
      that.close();
    }
  });

  this.eventManager.addEventListener(this.instance.view.wt.wtOverlays.leftOverlay.holder, 'scroll', function (event) {
    if (that.instance.view.wt.wtOverlays.leftOverlay.trimmingContainer != window) {
      that.hideCellPointer();
    }
  });

  this.eventManager.addEventListener(this.instance.view.wt.wtOverlays.topOverlay.holder, 'scroll', function (event) {
    if (that.instance.view.wt.wtOverlays.topOverlay.trimmingContainer != window) {
      that.hideCellPointer();
    }
  });
};

MobileTextEditor.prototype.destroy = function () {
  this.eventManager.clear();

  this.editorContainer.parentNode.removeChild(this.editorContainer);
};

exports.default = MobileTextEditor;

/***/ }),
/* 328 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


exports.__esModule = true;

var _createClass = 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); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

var _get = function get(object, property, receiver) { if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ("value" in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } };

var _numbro = __webpack_require__(52);

var _numbro2 = _interopRequireDefault(_numbro);

var _textEditor = __webpack_require__(44);

var _textEditor2 = _interopRequireDefault(_textEditor);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }

function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }

/**
 * @private
 * @editor NumericEditor
 * @class NumericEditor
 * @dependencies TextEditor numbro
 */
var NumericEditor = function (_TextEditor) {
  _inherits(NumericEditor, _TextEditor);

  function NumericEditor() {
    _classCallCheck(this, NumericEditor);

    return _possibleConstructorReturn(this, (NumericEditor.__proto__ || Object.getPrototypeOf(NumericEditor)).apply(this, arguments));
  }

  _createClass(NumericEditor, [{
    key: 'beginEditing',

    /**
     * @param {*} initialValue
     */
    value: function beginEditing(initialValue) {
      if (typeof initialValue === 'undefined' && this.originalValue) {
        if (typeof this.cellProperties.language !== 'undefined') {
          _numbro2.default.culture(this.cellProperties.language);
        }
        var decimalDelimiter = _numbro2.default.cultureData().delimiters.decimal;
        initialValue = ('' + this.originalValue).replace('.', decimalDelimiter);
      }
      _get(NumericEditor.prototype.__proto__ || Object.getPrototypeOf(NumericEditor.prototype), 'beginEditing', this).call(this, initialValue);
    }
  }]);

  return NumericEditor;
}(_textEditor2.default);

exports.default = NumericEditor;

/***/ }),
/* 329 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


exports.__esModule = true;

var _createClass = 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); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

var _get = function get(object, property, receiver) { if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ("value" in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } };

var _element = __webpack_require__(0);

var _textEditor = __webpack_require__(44);

var _textEditor2 = _interopRequireDefault(_textEditor);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }

function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }

/**
 * @private
 * @editor PasswordEditor
 * @class PasswordEditor
 * @dependencies TextEditor
 */
var PasswordEditor = function (_TextEditor) {
  _inherits(PasswordEditor, _TextEditor);

  function PasswordEditor() {
    _classCallCheck(this, PasswordEditor);

    return _possibleConstructorReturn(this, (PasswordEditor.__proto__ || Object.getPrototypeOf(PasswordEditor)).apply(this, arguments));
  }

  _createClass(PasswordEditor, [{
    key: 'createElements',
    value: function createElements() {
      _get(PasswordEditor.prototype.__proto__ || Object.getPrototypeOf(PasswordEditor.prototype), 'createElements', this).call(this);

      this.TEXTAREA = document.createElement('input');
      this.TEXTAREA.setAttribute('type', 'password');
      this.TEXTAREA.className = 'handsontableInput';
      this.textareaStyle = this.TEXTAREA.style;
      this.textareaStyle.width = 0;
      this.textareaStyle.height = 0;

      (0, _element.empty)(this.TEXTAREA_PARENT);
      this.TEXTAREA_PARENT.appendChild(this.TEXTAREA);
    }
  }]);

  return PasswordEditor;
}(_textEditor2.default);

exports.default = PasswordEditor;

/***/ }),
/* 330 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


exports.__esModule = true;

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

var _element = __webpack_require__(0);

var _event = __webpack_require__(7);

var _unicode = __webpack_require__(15);

var _baseEditor = __webpack_require__(36);

var _baseEditor2 = _interopRequireDefault(_baseEditor);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

var SelectEditor = _baseEditor2.default.prototype.extend();

/**
 * @private
 * @editor SelectEditor
 * @class SelectEditor
 */
SelectEditor.prototype.init = function () {
  this.select = document.createElement('SELECT');
  (0, _element.addClass)(this.select, 'htSelectEditor');
  this.select.style.display = 'none';
  this.instance.rootElement.appendChild(this.select);
  this.registerHooks();
};

SelectEditor.prototype.registerHooks = function () {
  var _this = this;

  this.instance.addHook('afterScrollHorizontally', function () {
    return _this.refreshDimensions();
  });
  this.instance.addHook('afterScrollVertically', function () {
    return _this.refreshDimensions();
  });
  this.instance.addHook('afterColumnResize', function () {
    return _this.refreshDimensions();
  });
  this.instance.addHook('afterRowResize', function () {
    return _this.refreshDimensions();
  });
};

SelectEditor.prototype.prepare = function () {
  _baseEditor2.default.prototype.prepare.apply(this, arguments);

  var selectOptions = this.cellProperties.selectOptions;
  var options;

  if (typeof selectOptions == 'function') {
    options = this.prepareOptions(selectOptions(this.row, this.col, this.prop));
  } else {
    options = this.prepareOptions(selectOptions);
  }

  (0, _element.empty)(this.select);

  for (var option in options) {
    if (Object.prototype.hasOwnProperty.call(options, option)) {
      var optionElement = document.createElement('OPTION');
      optionElement.value = option;
      (0, _element.fastInnerHTML)(optionElement, options[option]);
      this.select.appendChild(optionElement);
    }
  }
};

SelectEditor.prototype.prepareOptions = function (optionsToPrepare) {
  var preparedOptions = {};

  if (Array.isArray(optionsToPrepare)) {
    for (var i = 0, len = optionsToPrepare.length; i < len; i++) {
      preparedOptions[optionsToPrepare[i]] = optionsToPrepare[i];
    }
  } else if ((typeof optionsToPrepare === 'undefined' ? 'undefined' : _typeof(optionsToPrepare)) == 'object') {
    preparedOptions = optionsToPrepare;
  }

  return preparedOptions;
};

SelectEditor.prototype.getValue = function () {
  return this.select.value;
};

SelectEditor.prototype.setValue = function (value) {
  this.select.value = value;
};

var onBeforeKeyDown = function onBeforeKeyDown(event) {
  var instance = this;
  var editor = instance.getActiveEditor();

  switch (event.keyCode) {
    case _unicode.KEY_CODES.ARROW_UP:
      var previousOptionIndex = editor.select.selectedIndex - 1;
      if (previousOptionIndex >= 0) {
        editor.select[previousOptionIndex].selected = true;
      }

      (0, _event.stopImmediatePropagation)(event);
      event.preventDefault();
      break;

    case _unicode.KEY_CODES.ARROW_DOWN:
      var nextOptionIndex = editor.select.selectedIndex + 1;
      if (nextOptionIndex <= editor.select.length - 1) {
        editor.select[nextOptionIndex].selected = true;
      }

      (0, _event.stopImmediatePropagation)(event);
      event.preventDefault();
      break;
    default:
      break;
  }
};

SelectEditor.prototype.open = function () {
  this._opened = true;
  this.refreshDimensions();
  this.select.style.display = '';
  this.instance.addHook('beforeKeyDown', onBeforeKeyDown);
};

SelectEditor.prototype.close = function () {
  this._opened = false;
  this.select.style.display = 'none';
  this.instance.removeHook('beforeKeyDown', onBeforeKeyDown);
};

SelectEditor.prototype.focus = function () {
  this.select.focus();
};

SelectEditor.prototype.refreshValue = function () {
  var sourceData = this.instance.getSourceDataAtCell(this.row, this.prop);
  this.originalValue = sourceData;

  this.setValue(sourceData);
  this.refreshDimensions();
};

SelectEditor.prototype.refreshDimensions = function () {
  if (this.state !== _baseEditor.EditorState.EDITING) {
    return;
  }
  this.TD = this.getEditedCell();

  // TD is outside of the viewport.
  if (!this.TD) {
    this.close();

    return;
  }
  var width = (0, _element.outerWidth)(this.TD) + 1,
      height = (0, _element.outerHeight)(this.TD) + 1,
      currentOffset = (0, _element.offset)(this.TD),
      containerOffset = (0, _element.offset)(this.instance.rootElement),
      scrollableContainer = (0, _element.getScrollableElement)(this.TD),
      editTop = currentOffset.top - containerOffset.top - 1 - (scrollableContainer.scrollTop || 0),
      editLeft = currentOffset.left - containerOffset.left - 1 - (scrollableContainer.scrollLeft || 0),
      editorSection = this.checkEditorSection(),
      cssTransformOffset;

  var settings = this.instance.getSettings();
  var rowHeadersCount = settings.rowHeaders ? 1 : 0;
  var colHeadersCount = settings.colHeaders ? 1 : 0;

  switch (editorSection) {
    case 'top':
      cssTransformOffset = (0, _element.getCssTransform)(this.instance.view.wt.wtOverlays.topOverlay.clone.wtTable.holder.parentNode);
      break;
    case 'left':
      cssTransformOffset = (0, _element.getCssTransform)(this.instance.view.wt.wtOverlays.leftOverlay.clone.wtTable.holder.parentNode);
      break;
    case 'top-left-corner':
      cssTransformOffset = (0, _element.getCssTransform)(this.instance.view.wt.wtOverlays.topLeftCornerOverlay.clone.wtTable.holder.parentNode);
      break;
    case 'bottom-left-corner':
      cssTransformOffset = (0, _element.getCssTransform)(this.instance.view.wt.wtOverlays.bottomLeftCornerOverlay.clone.wtTable.holder.parentNode);
      break;
    case 'bottom':
      cssTransformOffset = (0, _element.getCssTransform)(this.instance.view.wt.wtOverlays.bottomOverlay.clone.wtTable.holder.parentNode);
      break;
    default:
      break;
  }
  if (this.instance.getSelected()[0] === 0) {
    editTop += 1;
  }

  if (this.instance.getSelected()[1] === 0) {
    editLeft += 1;
  }

  var selectStyle = this.select.style;

  if (cssTransformOffset && cssTransformOffset != -1) {
    selectStyle[cssTransformOffset[0]] = cssTransformOffset[1];
  } else {
    (0, _element.resetCssTransform)(this.select);
  }
  var cellComputedStyle = (0, _element.getComputedStyle)(this.TD);

  if (parseInt(cellComputedStyle.borderTopWidth, 10) > 0) {
    height -= 1;
  }
  if (parseInt(cellComputedStyle.borderLeftWidth, 10) > 0) {
    width -= 1;
  }

  selectStyle.height = height + 'px';
  selectStyle.minWidth = width + 'px';
  selectStyle.top = editTop + 'px';
  selectStyle.left = editLeft + 'px';
  selectStyle.margin = '0px';
};

SelectEditor.prototype.getEditedCell = function () {
  var editorSection = this.checkEditorSection(),
      editedCell;

  switch (editorSection) {
    case 'top':
      editedCell = this.instance.view.wt.wtOverlays.topOverlay.clone.wtTable.getCell({
        row: this.row,
        col: this.col
      });
      this.select.style.zIndex = 101;
      break;
    case 'corner':
      editedCell = this.instance.view.wt.wtOverlays.topLeftCornerOverlay.clone.wtTable.getCell({
        row: this.row,
        col: this.col
      });
      this.select.style.zIndex = 103;
      break;
    case 'left':
      editedCell = this.instance.view.wt.wtOverlays.leftOverlay.clone.wtTable.getCell({
        row: this.row,
        col: this.col
      });
      this.select.style.zIndex = 102;
      break;
    default:
      editedCell = this.instance.getCell(this.row, this.col);
      this.select.style.zIndex = '';
      break;
  }

  return editedCell != -1 && editedCell != -2 ? editedCell : void 0;
};

exports.default = SelectEditor;

/***/ }),
/* 331 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


exports.__esModule = true;
exports.toSingleLine = toSingleLine;

var _array = __webpack_require__(2);

/**
 * Tags a multiline string and return new one without line break characters and following spaces.
 *
 * @param {Array} strings Parts of the entire string without expressions.
 * @param {...String} expressions Expressions converted to strings, which are added to the entire string.
 * @returns {String}
 */
function toSingleLine(strings) {
  for (var _len = arguments.length, expressions = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
    expressions[_key - 1] = arguments[_key];
  }

  var result = (0, _array.arrayReduce)(strings, function (previousValue, currentValue, index) {

    var valueWithoutWhiteSpaces = currentValue.replace(/(?:\r?\n\s+)/g, '');
    var expressionForIndex = expressions[index] ? expressions[index] : '';

    return previousValue + valueWithoutWhiteSpaces + expressionForIndex;
  }, '');

  return result.trim();
} /* eslint-disable import/prefer-default-export */

/***/ }),
/* 332 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


__webpack_require__(98);

__webpack_require__(115);

__webpack_require__(124);

__webpack_require__(125);

__webpack_require__(109);

__webpack_require__(123);

__webpack_require__(106);

__webpack_require__(107);

__webpack_require__(108);

__webpack_require__(97);

__webpack_require__(120);

__webpack_require__(118);

__webpack_require__(116);

__webpack_require__(121);

__webpack_require__(122);

__webpack_require__(117);

__webpack_require__(119);

__webpack_require__(110);

__webpack_require__(111);

__webpack_require__(112);

__webpack_require__(114);

__webpack_require__(113);

__webpack_require__(95);

__webpack_require__(96);

__webpack_require__(91);

__webpack_require__(94);

__webpack_require__(93);

__webpack_require__(92);

__webpack_require__(70);

__webpack_require__(100);

__webpack_require__(101);

__webpack_require__(103);

__webpack_require__(102);

__webpack_require__(99);

__webpack_require__(105);

__webpack_require__(104);

__webpack_require__(126);

__webpack_require__(129);

__webpack_require__(127);

__webpack_require__(128);

__webpack_require__(131);

__webpack_require__(130);

__webpack_require__(133);

__webpack_require__(132);

__webpack_require__(293);

__webpack_require__(294);

__webpack_require__(295);

var _editors = __webpack_require__(13);

var _renderers = __webpack_require__(6);

var _validators = __webpack_require__(24);

var _cellTypes = __webpack_require__(65);

var _core = __webpack_require__(66);

var _core2 = _interopRequireDefault(_core);

var _jquery = __webpack_require__(296);

var _jquery2 = _interopRequireDefault(_jquery);

var _eventManager = __webpack_require__(4);

var _eventManager2 = _interopRequireDefault(_eventManager);

var _pluginHooks = __webpack_require__(11);

var _pluginHooks2 = _interopRequireDefault(_pluginHooks);

var _ghostTable = __webpack_require__(69);

var _ghostTable2 = _interopRequireDefault(_ghostTable);

var _array = __webpack_require__(2);

var arrayHelpers = _interopRequireWildcard(_array);

var _browser = __webpack_require__(22);

var browserHelpers = _interopRequireWildcard(_browser);

var _data = __webpack_require__(67);

var dataHelpers = _interopRequireWildcard(_data);

var _date = __webpack_require__(89);

var dateHelpers = _interopRequireWildcard(_date);

var _feature = __webpack_require__(34);

var featureHelpers = _interopRequireWildcard(_feature);

var _function = __webpack_require__(35);

var functionHelpers = _interopRequireWildcard(_function);

var _mixed = __webpack_require__(23);

var mixedHelpers = _interopRequireWildcard(_mixed);

var _number = __webpack_require__(5);

var numberHelpers = _interopRequireWildcard(_number);

var _object = __webpack_require__(3);

var objectHelpers = _interopRequireWildcard(_object);

var _setting = __webpack_require__(68);

var settingHelpers = _interopRequireWildcard(_setting);

var _string = __webpack_require__(28);

var stringHelpers = _interopRequireWildcard(_string);

var _unicode = __webpack_require__(15);

var unicodeHelpers = _interopRequireWildcard(_unicode);

var _element = __webpack_require__(0);

var domHelpers = _interopRequireWildcard(_element);

var _event = __webpack_require__(7);

var domEventHelpers = _interopRequireWildcard(_event);

var _index = __webpack_require__(297);

var plugins = _interopRequireWildcard(_index);

var _plugins = __webpack_require__(9);

var _defaultSettings = __webpack_require__(88);

var _defaultSettings2 = _interopRequireDefault(_defaultSettings);

var _rootInstance = __webpack_require__(90);

function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

function Handsontable(rootElement, userSettings) {
  var instance = new _core2.default(rootElement, userSettings || {}, _rootInstance.rootInstanceSymbol);

  instance.init();

  return instance;
}

(0, _jquery2.default)(Handsontable);

Handsontable.Core = _core2.default;
Handsontable.DefaultSettings = _defaultSettings2.default;
Handsontable.EventManager = _eventManager2.default;
Handsontable._getListenersCounter = _eventManager.getListenersCounter; // For MemoryLeak tests

Handsontable.buildDate = undefined;
Handsontable.packageName = undefined;
Handsontable.version = undefined;

var baseVersion = undefined;

if (baseVersion) {
  Handsontable.baseVersion = baseVersion;
}

// Export Hooks singleton
Handsontable.hooks = _pluginHooks2.default.getSingleton();

// TODO: Remove this exports after rewrite tests about this module
Handsontable.__GhostTable = _ghostTable2.default;
//

// Export all helpers to the Handsontable object
var HELPERS = [arrayHelpers, browserHelpers, dataHelpers, dateHelpers, featureHelpers, functionHelpers, mixedHelpers, numberHelpers, objectHelpers, settingHelpers, stringHelpers, unicodeHelpers];
var DOM = [domHelpers, domEventHelpers];

Handsontable.helper = {};
Handsontable.dom = {};

// Fill general helpers.
arrayHelpers.arrayEach(HELPERS, function (helper) {
  arrayHelpers.arrayEach(Object.getOwnPropertyNames(helper), function (key) {
    if (key.charAt(0) !== '_') {
      Handsontable.helper[key] = helper[key];
    }
  });
});

// Fill DOM helpers.
arrayHelpers.arrayEach(DOM, function (helper) {
  arrayHelpers.arrayEach(Object.getOwnPropertyNames(helper), function (key) {
    if (key.charAt(0) !== '_') {
      Handsontable.dom[key] = helper[key];
    }
  });
});

// Export cell types.
Handsontable.cellTypes = {};

arrayHelpers.arrayEach((0, _cellTypes.getRegisteredCellTypeNames)(), function (cellTypeName) {
  Handsontable.cellTypes[cellTypeName] = (0, _cellTypes.getCellType)(cellTypeName);
});

Handsontable.cellTypes.registerCellType = _cellTypes.registerCellType;
Handsontable.cellTypes.getCellType = _cellTypes.getCellType;

// Export all registered editors from the Handsontable.
Handsontable.editors = {};

arrayHelpers.arrayEach((0, _editors.getRegisteredEditorNames)(), function (editorName) {
  Handsontable.editors[stringHelpers.toUpperCaseFirst(editorName) + 'Editor'] = (0, _editors.getEditor)(editorName);
});

Handsontable.editors.registerEditor = _editors.registerEditor;
Handsontable.editors.getEditor = _editors.getEditor;

// Export all registered renderers from the Handsontable.
Handsontable.renderers = {};

arrayHelpers.arrayEach((0, _renderers.getRegisteredRendererNames)(), function (rendererName) {
  var renderer = (0, _renderers.getRenderer)(rendererName);

  if (rendererName === 'base') {
    Handsontable.renderers.cellDecorator = renderer;
  }
  Handsontable.renderers[stringHelpers.toUpperCaseFirst(rendererName) + 'Renderer'] = renderer;
});

Handsontable.renderers.registerRenderer = _renderers.registerRenderer;
Handsontable.renderers.getRenderer = _renderers.getRenderer;

// Export all registered validators from the Handsontable.
Handsontable.validators = {};

arrayHelpers.arrayEach((0, _validators.getRegisteredValidatorNames)(), function (validatorName) {
  Handsontable.validators[stringHelpers.toUpperCaseFirst(validatorName) + 'Validator'] = (0, _validators.getValidator)(validatorName);
});

Handsontable.validators.registerValidator = _validators.registerValidator;
Handsontable.validators.getValidator = _validators.getValidator;

// Export all registered plugins from the Handsontable.
Handsontable.plugins = {};

arrayHelpers.arrayEach(Object.getOwnPropertyNames(plugins), function (pluginName) {
  var plugin = plugins[pluginName];

  if (pluginName === 'Base') {
    Handsontable.plugins[pluginName + 'Plugin'] = plugin;
  } else {
    Handsontable.plugins[pluginName] = plugin;
  }
});

Handsontable.plugins.registerPlugin = _plugins.registerPlugin;

// Export Handsontable
module.exports = Handsontable;

/***/ }),
/* 333 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


exports.__esModule = true;

var _array = __webpack_require__(2);

var _object = __webpack_require__(3);

var MIXIN_NAME = 'localHooks';

/**
 * Mixin object to extend objects functionality for local hooks.
 *
 * @type {Object}
 */
var localHooks = {
  /**
   * Internal hooks storage.
   */
  _localHooks: Object.create(null),

  /**
   * Add hook to the collection.
   *
   * @param {String} key Hook name.
   * @param {Function} callback Hook callback
   */
  addLocalHook: function addLocalHook(key, callback) {
    if (!this._localHooks[key]) {
      this._localHooks[key] = [];
    }
    this._localHooks[key].push(callback);
  },


  /**
   * Run hooks.
   *
   * @param {String} key Hook name.
   * @param {*} params
   */
  runLocalHooks: function runLocalHooks(key) {
    var _this = this;

    for (var _len = arguments.length, params = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
      params[_key - 1] = arguments[_key];
    }

    if (this._localHooks[key]) {
      (0, _array.arrayEach)(this._localHooks[key], function (callback) {
        return callback.apply(_this, params);
      });
    }
  },


  /**
   * Clear all added hooks.
   */
  clearLocalHooks: function clearLocalHooks() {
    this._localHooks = {};
  }
};

(0, _object.defineGetter)(localHooks, 'MIXIN_NAME', MIXIN_NAME, {
  writable: false,
  enumerable: false
});

exports.default = localHooks;

/***/ }),
/* 334 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


exports.__esModule = true;

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

function MultiMap() {
  var map = {
    arrayMap: [],
    weakMap: new WeakMap()
  };

  return {
    get: function get(key) {
      if (canBeAnArrayMapKey(key)) {
        return map.arrayMap[key];
      } else if (canBeAWeakMapKey(key)) {
        return map.weakMap.get(key);
      }
    },
    set: function set(key, value) {
      if (canBeAnArrayMapKey(key)) {
        map.arrayMap[key] = value;
      } else if (canBeAWeakMapKey(key)) {
        map.weakMap.set(key, value);
      } else {
        throw new Error('Invalid key type');
      }
    },
    delete: function _delete(key) {
      if (canBeAnArrayMapKey(key)) {
        delete map.arrayMap[key];
      } else if (canBeAWeakMapKey(key)) {
        map.weakMap.delete(key);
      }
    }
  };

  function canBeAnArrayMapKey(obj) {
    return obj !== null && !isNaNSymbol(obj) && (typeof obj == 'string' || typeof obj == 'number');
  }

  function canBeAWeakMapKey(obj) {
    return obj !== null && ((typeof obj === 'undefined' ? 'undefined' : _typeof(obj)) == 'object' || typeof obj == 'function');
  }

  function isNaNSymbol(obj) {
    /* eslint-disable no-self-compare */
    return obj !== obj; // NaN === NaN is always false
  }
}

exports.default = MultiMap;

/***/ }),
/* 335 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


exports.__esModule = true;

var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }();

var _get = function get(object, property, receiver) { if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ("value" in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } };

var _createClass = 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); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

var _base = __webpack_require__(16);

var _base2 = _interopRequireDefault(_base);

var _array = __webpack_require__(2);

var _feature = __webpack_require__(34);

var _element = __webpack_require__(0);

var _ghostTable = __webpack_require__(69);

var _ghostTable2 = _interopRequireDefault(_ghostTable);

var _object = __webpack_require__(3);

var _number = __webpack_require__(5);

var _plugins = __webpack_require__(9);

var _samplesGenerator = __webpack_require__(269);

var _samplesGenerator2 = _interopRequireDefault(_samplesGenerator);

var _string = __webpack_require__(28);

var _src = __webpack_require__(14);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }

function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }

var privatePool = new WeakMap();

/**
 * @plugin AutoColumnSize
 *
 * @description
 * This plugin allows to set column widths based on their widest cells.
 *
 * By default, the plugin is declared as `undefined`, which makes it enabled (same as if it was declared as `true`).
 * Enabling this plugin may decrease the overall table performance, as it needs to calculate the widths of all cells to
 * resize the columns accordingly.
 * If you experience problems with the performance, try turning this feature off and declaring the column widths manually.
 *
 * Column width calculations are divided into sync and async part. Each of this parts has their own advantages and
 * disadvantages. Synchronous calculations are faster but they block the browser UI, while the slower asynchronous operations don't
 * block the browser UI.
 *
 * To configure the sync/async distribution, you can pass an absolute value (number of columns) or a percentage value to a config object:
 * ```js
 * ...
 * // as a number (300 columns in sync, rest async)
 * autoColumnSize: {syncLimit: 300},
 * ...
 *
 * ...
 * // as a string (percent)
 * autoColumnSize: {syncLimit: '40%'},
 * ...
 * ```
 *
 * To configure this plugin see {@link Options#autoColumnSize}.
 *
 * @example
 * ```js
 * ...
 * var hot = new Handsontable(document.getElementById('example'), {
 *   date: getData(),
 *   autoColumnSize: true
 * });
 * // Access to plugin instance:
 * var plugin = hot.getPlugin('autoColumnSize');
 *
 * plugin.getColumnWidth(4);
 *
 * if (plugin.isEnabled()) {
 *   // code...
 * }
 * ...
 * ```
 */

var AutoColumnSize = function (_BasePlugin) {
  _inherits(AutoColumnSize, _BasePlugin);

  _createClass(AutoColumnSize, null, [{
    key: 'CALCULATION_STEP',
    get: function get() {
      return 50;
    }
  }, {
    key: 'SYNC_CALCULATION_LIMIT',
    get: function get() {
      return 50;
    }
  }]);

  function AutoColumnSize(hotInstance) {
    _classCallCheck(this, AutoColumnSize);

    var _this = _possibleConstructorReturn(this, (AutoColumnSize.__proto__ || Object.getPrototypeOf(AutoColumnSize)).call(this, hotInstance));

    privatePool.set(_this, {
      /**
       * Cached column header names. It is used to diff current column headers with previous state and detect which
       * columns width should be updated.
       *
       * @private
       * @type {Array}
       */
      cachedColumnHeaders: []
    });
    /**
     * Cached columns widths.
     *
     * @type {Array}
     */
    _this.widths = [];
    /**
     * Instance of {@link GhostTable} for rows and columns size calculations.
     *
     * @type {GhostTable}
     */
    _this.ghostTable = new _ghostTable2.default(_this.hot);
    /**
     * Instance of {@link SamplesGenerator} for generating samples necessary for columns width calculations.
     *
     * @type {SamplesGenerator}
     */
    _this.samplesGenerator = new _samplesGenerator2.default(function (row, col) {
      return _this.hot.getDataAtCell(row, col);
    });
    /**
     * `true` only if the first calculation was performed
     *
     * @type {Boolean}
     */
    _this.firstCalculation = true;
    /**
     * `true` if the size calculation is in progress.
     *
     * @type {Boolean}
     */
    _this.inProgress = false;

    // moved to constructor to allow auto-sizing the columns when the plugin is disabled
    _this.addHook('beforeColumnResize', function (col, size, isDblClick) {
      return _this.onBeforeColumnResize(col, size, isDblClick);
    });
    return _this;
  }

  /**
   * Check if the plugin is enabled in the handsontable settings.
   *
   * @returns {Boolean}
   */


  _createClass(AutoColumnSize, [{
    key: 'isEnabled',
    value: function isEnabled() {
      return this.hot.getSettings().autoColumnSize !== false && !this.hot.getSettings().colWidths;
    }

    /**
     * Enable plugin for this Handsontable instance.
     */

  }, {
    key: 'enablePlugin',
    value: function enablePlugin() {
      var _this2 = this;

      if (this.enabled) {
        return;
      }

      var setting = this.hot.getSettings().autoColumnSize;

      if (setting && setting.useHeaders != null) {
        this.ghostTable.setSetting('useHeaders', setting.useHeaders);
      }

      this.addHook('afterLoadData', function () {
        return _this2.onAfterLoadData();
      });
      this.addHook('beforeChange', function (changes) {
        return _this2.onBeforeChange(changes);
      });

      this.addHook('beforeRender', function (force) {
        return _this2.onBeforeRender(force);
      });
      this.addHook('modifyColWidth', function (width, col) {
        return _this2.getColumnWidth(col, width);
      });
      this.addHook('afterInit', function () {
        return _this2.onAfterInit();
      });
      _get(AutoColumnSize.prototype.__proto__ || Object.getPrototypeOf(AutoColumnSize.prototype), 'enablePlugin', this).call(this);
    }

    /**
     * Update plugin state.
     */

  }, {
    key: 'updatePlugin',
    value: function updatePlugin() {
      var changedColumns = this.findColumnsWhereHeaderWasChanged();

      if (changedColumns.length) {
        this.clearCache(changedColumns);
      }
      _get(AutoColumnSize.prototype.__proto__ || Object.getPrototypeOf(AutoColumnSize.prototype), 'updatePlugin', this).call(this);
    }

    /**
     * Disable plugin for this Handsontable instance.
     */

  }, {
    key: 'disablePlugin',
    value: function disablePlugin() {
      _get(AutoColumnSize.prototype.__proto__ || Object.getPrototypeOf(AutoColumnSize.prototype), 'disablePlugin', this).call(this);
    }

    /**
     * Calculate a columns width.
     *
     * @param {Number|Object} colRange Column range object.
     * @param {Number|Object} rowRange Row range object.
     * @param {Boolean} [force=false] If `true` force calculate width even when value was cached earlier.
     */

  }, {
    key: 'calculateColumnsWidth',
    value: function calculateColumnsWidth() {
      var colRange = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : { from: 0, to: this.hot.countCols() - 1 };

      var _this3 = this;

      var rowRange = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : { from: 0, to: this.hot.countRows() - 1 };
      var force = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;

      if (typeof colRange === 'number') {
        colRange = { from: colRange, to: colRange };
      }
      if (typeof rowRange === 'number') {
        rowRange = { from: rowRange, to: rowRange };
      }

      (0, _number.rangeEach)(colRange.from, colRange.to, function (col) {
        if (force || _this3.widths[col] === void 0 && !_this3.hot._getColWidthFromSettings(col)) {
          var samples = _this3.samplesGenerator.generateColumnSamples(col, rowRange);

          samples.forEach(function (sample, col) {
            return _this3.ghostTable.addColumn(col, sample);
          });
        }
      });

      if (this.ghostTable.columns.length) {
        this.ghostTable.getWidths(function (col, width) {
          _this3.widths[col] = width;
        });
        this.ghostTable.clean();
      }
    }

    /**
     * Calculate all columns width.
     *
     * @param {Object|Number} rowRange Row range object.
     */

  }, {
    key: 'calculateAllColumnsWidth',
    value: function calculateAllColumnsWidth() {
      var _this4 = this;

      var rowRange = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : { from: 0, to: this.hot.countRows() - 1 };

      var current = 0;
      var length = this.hot.countCols() - 1;
      var timer = null;

      this.inProgress = true;

      var loop = function loop() {
        // When hot was destroyed after calculating finished cancel frame
        if (!_this4.hot) {
          (0, _feature.cancelAnimationFrame)(timer);
          _this4.inProgress = false;

          return;
        }

        _this4.calculateColumnsWidth({
          from: current,
          to: Math.min(current + AutoColumnSize.CALCULATION_STEP, length)
        }, rowRange);

        current = current + AutoColumnSize.CALCULATION_STEP + 1;

        if (current < length) {
          timer = (0, _feature.requestAnimationFrame)(loop);
        } else {
          (0, _feature.cancelAnimationFrame)(timer);
          _this4.inProgress = false;

          // @TODO Should call once per render cycle, currently fired separately in different plugins
          _this4.hot.view.wt.wtOverlays.adjustElementsSize(true);
          // tmp
          if (_this4.hot.view.wt.wtOverlays.leftOverlay.needFullRender) {
            _this4.hot.view.wt.wtOverlays.leftOverlay.clone.draw();
          }
        }
      };
      // sync
      if (this.firstCalculation && this.getSyncCalculationLimit()) {
        this.calculateColumnsWidth({ from: 0, to: this.getSyncCalculationLimit() }, rowRange);
        this.firstCalculation = false;
        current = this.getSyncCalculationLimit() + 1;
      }
      // async
      if (current < length) {
        loop();
      } else {
        this.inProgress = false;
      }
    }

    /**
     * Set the sampling options.
     *
     * @private
     */

  }, {
    key: 'setSamplingOptions',
    value: function setSamplingOptions() {
      var setting = this.hot.getSettings().autoColumnSize;
      var samplingRatio = setting && (0, _object.hasOwnProperty)(setting, 'samplingRatio') ? this.hot.getSettings().autoColumnSize.samplingRatio : void 0;
      var allowSampleDuplicates = setting && (0, _object.hasOwnProperty)(setting, 'allowSampleDuplicates') ? this.hot.getSettings().autoColumnSize.allowSampleDuplicates : void 0;

      if (samplingRatio && !isNaN(samplingRatio)) {
        this.samplesGenerator.setSampleCount(parseInt(samplingRatio, 10));
      }

      if (allowSampleDuplicates) {
        this.samplesGenerator.setAllowDuplicates(allowSampleDuplicates);
      }
    }

    /**
     * Recalculate all columns width (overwrite cache values).
     */

  }, {
    key: 'recalculateAllColumnsWidth',
    value: function recalculateAllColumnsWidth() {
      if (this.hot.view && (0, _element.isVisible)(this.hot.view.wt.wtTable.TABLE)) {
        this.clearCache();
        this.calculateAllColumnsWidth();
      }
    }

    /**
     * Get value which tells how many columns should be calculated synchronously. Rest of the columns will be calculated asynchronously.
     *
     * @returns {Number}
     */

  }, {
    key: 'getSyncCalculationLimit',
    value: function getSyncCalculationLimit() {
      /* eslint-disable no-bitwise */
      var limit = AutoColumnSize.SYNC_CALCULATION_LIMIT;
      var colsLimit = this.hot.countCols() - 1;

      if ((0, _object.isObject)(this.hot.getSettings().autoColumnSize)) {
        limit = this.hot.getSettings().autoColumnSize.syncLimit;

        if ((0, _string.isPercentValue)(limit)) {
          limit = (0, _number.valueAccordingPercent)(colsLimit, limit);
        } else {
          // Force to Number
          limit >>= 0;
        }
      }

      return Math.min(limit, colsLimit);
    }

    /**
     * Get the calculated column width.
     *
     * @param {Number} col Column index.
     * @param {Number} [defaultWidth] Default column width. It will be picked up if no calculated width found.
     * @param {Boolean} [keepMinimum=true] If `true` then returned value won't be smaller then 50 (default column width).
     * @returns {Number}
     */

  }, {
    key: 'getColumnWidth',
    value: function getColumnWidth(col) {
      var defaultWidth = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : void 0;
      var keepMinimum = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true;

      var width = defaultWidth;

      if (width === void 0) {
        width = this.widths[col];

        if (keepMinimum && typeof width === 'number') {
          width = Math.max(width, _src.ViewportColumnsCalculator.DEFAULT_WIDTH);
        }
      }

      return width;
    }

    /**
     * Get the first visible column.
     *
     * @returns {Number} Returns column index or -1 if table is not rendered.
     */

  }, {
    key: 'getFirstVisibleColumn',
    value: function getFirstVisibleColumn() {
      var wot = this.hot.view.wt;

      if (wot.wtViewport.columnsVisibleCalculator) {
        return wot.wtTable.getFirstVisibleColumn();
      }
      if (wot.wtViewport.columnsRenderCalculator) {
        return wot.wtTable.getFirstRenderedColumn();
      }

      return -1;
    }

    /**
     * Get the last visible column.
     *
     * @returns {Number} Returns column index or -1 if table is not rendered.
     */

  }, {
    key: 'getLastVisibleColumn',
    value: function getLastVisibleColumn() {
      var wot = this.hot.view.wt;

      if (wot.wtViewport.columnsVisibleCalculator) {
        return wot.wtTable.getLastVisibleColumn();
      }
      if (wot.wtViewport.columnsRenderCalculator) {
        return wot.wtTable.getLastRenderedColumn();
      }

      return -1;
    }

    /**
     * Collects all columns which titles has been changed in comparison to the previous state.
     *
     * @returns {Array} It returns an array of physical column indexes.
     */

  }, {
    key: 'findColumnsWhereHeaderWasChanged',
    value: function findColumnsWhereHeaderWasChanged() {
      var columnHeaders = this.hot.getColHeader();

      var _privatePool$get = privatePool.get(this),
          cachedColumnHeaders = _privatePool$get.cachedColumnHeaders;

      var changedColumns = (0, _array.arrayReduce)(columnHeaders, function (acc, columnTitle, physicalColumn) {
        var cachedColumnsLength = cachedColumnHeaders.length;

        if (cachedColumnsLength - 1 < physicalColumn || cachedColumnHeaders[physicalColumn] !== columnTitle) {
          acc.push(physicalColumn);
        }
        if (cachedColumnsLength - 1 < physicalColumn) {
          cachedColumnHeaders.push(columnTitle);
        } else {
          cachedColumnHeaders[physicalColumn] = columnTitle;
        }

        return acc;
      }, []);

      return changedColumns;
    }

    /**
     * Clear cache of calculated column widths. If you want to clear only selected columns pass an array with their indexes.
     * Otherwise whole cache will be cleared.
     *
     * @param {Array} [columns=[]] List of column indexes (physical indexes) to clear.
     */

  }, {
    key: 'clearCache',
    value: function clearCache() {
      var _this5 = this;

      var columns = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];

      if (columns.length) {
        (0, _array.arrayEach)(columns, function (physicalIndex) {
          _this5.widths[physicalIndex] = void 0;
        });
      } else {
        this.widths.length = 0;
      }
    }

    /**
     * Check if all widths were calculated. If not then return `true` (need recalculate).
     *
     * @returns {Boolean}
     */

  }, {
    key: 'isNeedRecalculate',
    value: function isNeedRecalculate() {
      return !!(0, _array.arrayFilter)(this.widths, function (item) {
        return item === void 0;
      }).length;
    }

    /**
     * On before render listener.
     *
     * @private
     */

  }, {
    key: 'onBeforeRender',
    value: function onBeforeRender() {
      var force = this.hot.renderCall;
      var rowsCount = this.hot.countRows();

      // Keep last column widths unchanged for situation when all rows was deleted or trimmed (pro #6)
      if (!rowsCount) {
        return;
      }

      this.calculateColumnsWidth({ from: this.getFirstVisibleColumn(), to: this.getLastVisibleColumn() }, void 0, force);

      if (this.isNeedRecalculate() && !this.inProgress) {
        this.calculateAllColumnsWidth();
      }
    }

    /**
     * On after load data listener.
     *
     * @private
     */

  }, {
    key: 'onAfterLoadData',
    value: function onAfterLoadData() {
      var _this6 = this;

      if (this.hot.view) {
        this.recalculateAllColumnsWidth();
      } else {
        // first load - initialization
        setTimeout(function () {
          if (_this6.hot) {
            _this6.recalculateAllColumnsWidth();
          }
        }, 0);
      }
    }

    /**
     * On before change listener.
     *
     * @private
     * @param {Array} changes
     */

  }, {
    key: 'onBeforeChange',
    value: function onBeforeChange(changes) {
      var _this7 = this;

      var changedColumns = (0, _array.arrayMap)(changes, function (_ref) {
        var _ref2 = _slicedToArray(_ref, 2),
            row = _ref2[0],
            column = _ref2[1];

        return _this7.hot.propToCol(column);
      });

      this.clearCache(changedColumns);
    }

    /**
     * On before column resize listener.
     *
     * @private
     * @param {Number} col
     * @param {Number} size
     * @param {Boolean} isDblClick
     * @returns {Number}
     */

  }, {
    key: 'onBeforeColumnResize',
    value: function onBeforeColumnResize(col, size, isDblClick) {
      if (isDblClick) {
        this.calculateColumnsWidth(col, void 0, true);
        size = this.getColumnWidth(col, void 0, false);
      }

      return size;
    }

    /**
     * On after Handsontable init fill plugin with all necessary values.
     *
     * @private
     */

  }, {
    key: 'onAfterInit',
    value: function onAfterInit() {
      privatePool.get(this).cachedColumnHeaders = this.hot.getColHeader();
    }

    /**
     * Destroy plugin instance.
     */

  }, {
    key: 'destroy',
    value: function destroy() {
      this.ghostTable.clean();
      _get(AutoColumnSize.prototype.__proto__ || Object.getPrototypeOf(AutoColumnSize.prototype), 'destroy', this).call(this);
    }
  }]);

  return AutoColumnSize;
}(_base2.default);

(0, _plugins.registerPlugin)('autoColumnSize', AutoColumnSize);

exports.default = AutoColumnSize;

/***/ }),
/* 336 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


exports.__esModule = true;

var _get = function get(object, property, receiver) { if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ("value" in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } };

var _createClass = 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); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

var _base = __webpack_require__(16);

var _base2 = _interopRequireDefault(_base);

var _array = __webpack_require__(2);

var _feature = __webpack_require__(34);

var _element = __webpack_require__(0);

var _ghostTable = __webpack_require__(69);

var _ghostTable2 = _interopRequireDefault(_ghostTable);

var _object = __webpack_require__(3);

var _number = __webpack_require__(5);

var _plugins = __webpack_require__(9);

var _samplesGenerator = __webpack_require__(269);

var _samplesGenerator2 = _interopRequireDefault(_samplesGenerator);

var _string = __webpack_require__(28);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }

function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }

/**
 * @plugin AutoRowSize
 *
 * @description
 * This plugin allows to set row heights based on their highest cells.
 *
 * By default, the plugin is declared as `undefined`, which makes it disabled (same as if it was declared as `false`).
 * Enabling this plugin may decrease the overall table performance, as it needs to calculate the heights of all cells to
 * resize the rows accordingly.
 * If you experience problems with the performance, try turning this feature off and declaring the row heights manually.
 *
 * Row height calculations are divided into sync and async part. Each of this parts has their own advantages and
 * disadvantages. Synchronous calculations are faster but they block the browser UI, while the slower asynchronous operations don't
 * block the browser UI.
 *
 * To configure the sync/async distribution, you can pass an absolute value (number of columns) or a percentage value to a config object:
 * ```js
 * ...
 * // as a number (300 columns in sync, rest async)
 * autoRowSize: {syncLimit: 300},
 * ...
 *
 * ...
 * // as a string (percent)
 * autoRowSize: {syncLimit: '40%'},
 * ...
 * ```
 *
 * You can also use the `allowSampleDuplicates` option to allow sampling duplicate values when calculating the row height. Note, that this might have
 * a negative impact on performance.
 *
 * To configure this plugin see {@link Options#autoRowSize}.
 *
 * @example
 *
 * ```js
 * ...
 * var hot = new Handsontable(document.getElementById('example'), {
 *   date: getData(),
 *   autoRowSize: true
 * });
 * // Access to plugin instance:
 * var plugin = hot.getPlugin('autoRowSize');
 *
 * plugin.getRowHeight(4);
 *
 * if (plugin.isEnabled()) {
 *   // code...
 * }
 * ...
 * ```
 */
var AutoRowSize = function (_BasePlugin) {
  _inherits(AutoRowSize, _BasePlugin);

  _createClass(AutoRowSize, null, [{
    key: 'CALCULATION_STEP',
    get: function get() {
      return 50;
    }
  }, {
    key: 'SYNC_CALCULATION_LIMIT',
    get: function get() {
      return 500;
    }
  }]);

  function AutoRowSize(hotInstance) {
    _classCallCheck(this, AutoRowSize);

    /**
     * Cached rows heights.
     *
     * @type {Array}
     */
    var _this = _possibleConstructorReturn(this, (AutoRowSize.__proto__ || Object.getPrototypeOf(AutoRowSize)).call(this, hotInstance));

    _this.heights = [];
    /**
     * Instance of {@link GhostTable} for rows and columns size calculations.
     *
     * @type {GhostTable}
     */
    _this.ghostTable = new _ghostTable2.default(_this.hot);
    /**
     * Instance of {@link SamplesGenerator} for generating samples necessary for rows height calculations.
     *
     * @type {SamplesGenerator}
     */
    _this.samplesGenerator = new _samplesGenerator2.default(function (row, col) {
      if (row >= 0) {
        return _this.hot.getDataAtCell(row, col);
      } else if (row === -1) {
        return _this.hot.getColHeader(col);
      }
      return null;
    });
    /**
     * `true` if only the first calculation was performed.
     *
     * @type {Boolean}
     */
    _this.firstCalculation = true;
    /**
     * `true` if the size calculation is in progress.
     *
     * @type {Boolean}
     */
    _this.inProgress = false;

    // moved to constructor to allow auto-sizing the rows when the plugin is disabled
    _this.addHook('beforeRowResize', function (row, size, isDblClick) {
      return _this.onBeforeRowResize(row, size, isDblClick);
    });
    return _this;
  }

  /**
   * Check if the plugin is enabled in the Handsontable settings.
   *
   * @returns {Boolean}
   */


  _createClass(AutoRowSize, [{
    key: 'isEnabled',
    value: function isEnabled() {
      return this.hot.getSettings().autoRowSize === true || (0, _object.isObject)(this.hot.getSettings().autoRowSize);
    }

    /**
     * Enable plugin for this Handsontable instance.
     */

  }, {
    key: 'enablePlugin',
    value: function enablePlugin() {
      var _this2 = this;

      if (this.enabled) {
        return;
      }

      this.setSamplingOptions();

      this.addHook('afterLoadData', function () {
        return _this2.onAfterLoadData();
      });
      this.addHook('beforeChange', function (changes) {
        return _this2.onBeforeChange(changes);
      });
      this.addHook('beforeColumnMove', function () {
        return _this2.recalculateAllRowsHeight();
      });
      this.addHook('beforeColumnResize', function () {
        return _this2.recalculateAllRowsHeight();
      });
      this.addHook('beforeColumnSort', function () {
        return _this2.clearCache();
      });
      this.addHook('beforeRender', function (force) {
        return _this2.onBeforeRender(force);
      });
      this.addHook('beforeRowMove', function (rowStart, rowEnd) {
        return _this2.onBeforeRowMove(rowStart, rowEnd);
      });
      this.addHook('modifyRowHeight', function (height, row) {
        return _this2.getRowHeight(row, height);
      });
      this.addHook('modifyColumnHeaderHeight', function () {
        return _this2.getColumnHeaderHeight();
      });
      _get(AutoRowSize.prototype.__proto__ || Object.getPrototypeOf(AutoRowSize.prototype), 'enablePlugin', this).call(this);
    }

    /**
     * Disable plugin for this Handsontable instance.
     */

  }, {
    key: 'disablePlugin',
    value: function disablePlugin() {
      _get(AutoRowSize.prototype.__proto__ || Object.getPrototypeOf(AutoRowSize.prototype), 'disablePlugin', this).call(this);
    }

    /**
     * Calculate a given rows height.
     *
     * @param {Number|Object} rowRange Row range object.
     * @param {Number|Object} colRange Column range object.
     * @param {Boolean} [force=false] If `true` force calculate height even when value was cached earlier.
     */

  }, {
    key: 'calculateRowsHeight',
    value: function calculateRowsHeight() {
      var rowRange = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : { from: 0, to: this.hot.countRows() - 1 };

      var _this3 = this;

      var colRange = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : { from: 0, to: this.hot.countCols() - 1 };
      var force = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;

      if (typeof rowRange === 'number') {
        rowRange = { from: rowRange, to: rowRange };
      }
      if (typeof colRange === 'number') {
        colRange = { from: colRange, to: colRange };
      }

      if (this.hot.getColHeader(0) !== null) {
        var samples = this.samplesGenerator.generateRowSamples(-1, colRange);

        this.ghostTable.addColumnHeadersRow(samples.get(-1));
      }

      (0, _number.rangeEach)(rowRange.from, rowRange.to, function (row) {
        // For rows we must calculate row height even when user had set height value manually.
        // We can shrink column but cannot shrink rows!
        if (force || _this3.heights[row] === void 0) {
          var _samples = _this3.samplesGenerator.generateRowSamples(row, colRange);

          _samples.forEach(function (sample, row) {
            _this3.ghostTable.addRow(row, sample);
          });
        }
      });
      if (this.ghostTable.rows.length) {
        this.ghostTable.getHeights(function (row, height) {
          _this3.heights[row] = height;
        });
        this.ghostTable.clean();
      }
    }

    /**
     * Calculate the height of all the rows.
     *
     * @param {Object|Number} colRange Column range object.
     */

  }, {
    key: 'calculateAllRowsHeight',
    value: function calculateAllRowsHeight() {
      var _this4 = this;

      var colRange = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : { from: 0, to: this.hot.countCols() - 1 };

      var current = 0;
      var length = this.hot.countRows() - 1;
      var timer = null;

      this.inProgress = true;

      var loop = function loop() {
        // When hot was destroyed after calculating finished cancel frame
        if (!_this4.hot) {
          (0, _feature.cancelAnimationFrame)(timer);
          _this4.inProgress = false;

          return;
        }
        _this4.calculateRowsHeight({ from: current, to: Math.min(current + AutoRowSize.CALCULATION_STEP, length) }, colRange);
        current = current + AutoRowSize.CALCULATION_STEP + 1;

        if (current < length) {
          timer = (0, _feature.requestAnimationFrame)(loop);
        } else {
          (0, _feature.cancelAnimationFrame)(timer);
          _this4.inProgress = false;

          // @TODO Should call once per render cycle, currently fired separately in different plugins
          _this4.hot.view.wt.wtOverlays.adjustElementsSize(true);
          // tmp
          if (_this4.hot.view.wt.wtOverlays.leftOverlay.needFullRender) {
            _this4.hot.view.wt.wtOverlays.leftOverlay.clone.draw();
          }
        }
      };
      // sync
      if (this.firstCalculation && this.getSyncCalculationLimit()) {
        this.calculateRowsHeight({ from: 0, to: this.getSyncCalculationLimit() }, colRange);
        this.firstCalculation = false;
        current = this.getSyncCalculationLimit() + 1;
      }
      // async
      if (current < length) {
        loop();
      } else {
        this.inProgress = false;
        this.hot.view.wt.wtOverlays.adjustElementsSize(false);
      }
    }

    /**
     * Set the sampling options.
     *
     * @private
     */

  }, {
    key: 'setSamplingOptions',
    value: function setSamplingOptions() {
      var setting = this.hot.getSettings().autoRowSize;
      var samplingRatio = setting && (0, _object.hasOwnProperty)(setting, 'samplingRatio') ? this.hot.getSettings().autoRowSize.samplingRatio : void 0;
      var allowSampleDuplicates = setting && (0, _object.hasOwnProperty)(setting, 'allowSampleDuplicates') ? this.hot.getSettings().autoRowSize.allowSampleDuplicates : void 0;

      if (samplingRatio && !isNaN(samplingRatio)) {
        this.samplesGenerator.setSampleCount(parseInt(samplingRatio, 10));
      }

      if (allowSampleDuplicates) {
        this.samplesGenerator.setAllowDuplicates(allowSampleDuplicates);
      }
    }

    /**
     * Recalculate all rows height (overwrite cache values).
     */

  }, {
    key: 'recalculateAllRowsHeight',
    value: function recalculateAllRowsHeight() {
      if ((0, _element.isVisible)(this.hot.view.wt.wtTable.TABLE)) {
        this.clearCache();
        this.calculateAllRowsHeight();
      }
    }

    /**
     * Get value which tells how much rows will be calculated synchronously. Rest rows will be calculated asynchronously.
     *
     * @returns {Number}
     */

  }, {
    key: 'getSyncCalculationLimit',
    value: function getSyncCalculationLimit() {
      /* eslint-disable no-bitwise */
      var limit = AutoRowSize.SYNC_CALCULATION_LIMIT;
      var rowsLimit = this.hot.countRows() - 1;

      if ((0, _object.isObject)(this.hot.getSettings().autoRowSize)) {
        limit = this.hot.getSettings().autoRowSize.syncLimit;

        if ((0, _string.isPercentValue)(limit)) {
          limit = (0, _number.valueAccordingPercent)(rowsLimit, limit);
        } else {
          // Force to Number
          limit >>= 0;
        }
      }

      return Math.min(limit, rowsLimit);
    }

    /**
     * Get the calculated row height.
     *
     * @param {Number} row Visual row index.
     * @param {Number} [defaultHeight] Default row height. It will be pick up if no calculated height found.
     * @returns {Number}
     */

  }, {
    key: 'getRowHeight',
    value: function getRowHeight(row) {
      var defaultHeight = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : void 0;

      var height = defaultHeight;

      if (this.heights[row] !== void 0 && this.heights[row] > (defaultHeight || 0)) {
        height = this.heights[row];
      }

      return height;
    }

    /**
     * Get the calculated column header height.
     *
     * @returns {Number|undefined}
     */

  }, {
    key: 'getColumnHeaderHeight',
    value: function getColumnHeaderHeight() {
      return this.heights[-1];
    }

    /**
     * Get the first visible row.
     *
     * @returns {Number} Returns row index or -1 if table is not rendered.
     */

  }, {
    key: 'getFirstVisibleRow',
    value: function getFirstVisibleRow() {
      var wot = this.hot.view.wt;

      if (wot.wtViewport.rowsVisibleCalculator) {
        return wot.wtTable.getFirstVisibleRow();
      }
      if (wot.wtViewport.rowsRenderCalculator) {
        return wot.wtTable.getFirstRenderedRow();
      }

      return -1;
    }

    /**
     * Get the last visible row.
     *
     * @returns {Number} Returns row index or -1 if table is not rendered.
     */

  }, {
    key: 'getLastVisibleRow',
    value: function getLastVisibleRow() {
      var wot = this.hot.view.wt;

      if (wot.wtViewport.rowsVisibleCalculator) {
        return wot.wtTable.getLastVisibleRow();
      }
      if (wot.wtViewport.rowsRenderCalculator) {
        return wot.wtTable.getLastRenderedRow();
      }

      return -1;
    }

    /**
     * Clear cached heights.
     */

  }, {
    key: 'clearCache',
    value: function clearCache() {
      this.heights.length = 0;
      this.heights[-1] = void 0;
    }

    /**
     * Clear cache by range.
     *
     * @param {Object|Number} range Row range object.
     */

  }, {
    key: 'clearCacheByRange',
    value: function clearCacheByRange(range) {
      var _this5 = this;

      if (typeof range === 'number') {
        range = { from: range, to: range };
      }
      (0, _number.rangeEach)(Math.min(range.from, range.to), Math.max(range.from, range.to), function (row) {
        _this5.heights[row] = void 0;
      });
    }

    /**
     * @returns {Boolean}
     */

  }, {
    key: 'isNeedRecalculate',
    value: function isNeedRecalculate() {
      return !!(0, _array.arrayFilter)(this.heights, function (item) {
        return item === void 0;
      }).length;
    }

    /**
     * On before render listener.
     *
     * @private
     */

  }, {
    key: 'onBeforeRender',
    value: function onBeforeRender() {
      var force = this.hot.renderCall;
      this.calculateRowsHeight({ from: this.getFirstVisibleRow(), to: this.getLastVisibleRow() }, void 0, force);

      var fixedRowsBottom = this.hot.getSettings().fixedRowsBottom;

      // Calculate rows height synchronously for bottom overlay
      if (fixedRowsBottom) {
        var totalRows = this.hot.countRows() - 1;
        this.calculateRowsHeight({ from: totalRows - fixedRowsBottom, to: totalRows });
      }

      if (this.isNeedRecalculate() && !this.inProgress) {
        this.calculateAllRowsHeight();
      }
    }

    /**
     * On before row move listener.
     *
     * @private
     * @param {Number} from Row index where was grabbed.
     * @param {Number} to Destination row index.
     */

  }, {
    key: 'onBeforeRowMove',
    value: function onBeforeRowMove(from, to) {
      this.clearCacheByRange({ from: from, to: to });
      this.calculateAllRowsHeight();
    }

    /**
     * On before row resize listener.
     *
     * @private
     * @param {Number} row
     * @param {Number} size
     * @param {Boolean} isDblClick
     * @returns {Number}
     */

  }, {
    key: 'onBeforeRowResize',
    value: function onBeforeRowResize(row, size, isDblClick) {
      if (isDblClick) {
        this.calculateRowsHeight(row, void 0, true);
        size = this.getRowHeight(row);
      }

      return size;
    }

    /**
     * On after load data listener.
     *
     * @private
     */

  }, {
    key: 'onAfterLoadData',
    value: function onAfterLoadData() {
      var _this6 = this;

      if (this.hot.view) {
        this.recalculateAllRowsHeight();
      } else {
        // first load - initialization
        setTimeout(function () {
          if (_this6.hot) {
            _this6.recalculateAllRowsHeight();
          }
        }, 0);
      }
    }

    /**
     * On before change listener.
     *
     * @private
     * @param {Array} changes
     */

  }, {
    key: 'onBeforeChange',
    value: function onBeforeChange(changes) {
      var range = null;

      if (changes.length === 1) {
        range = changes[0][0];
      } else if (changes.length > 1) {
        range = {
          from: changes[0][0],
          to: changes[changes.length - 1][0]
        };
      }
      if (range !== null) {
        this.clearCacheByRange(range);
      }
    }

    /**
     * Destroy plugin instance.
     */

  }, {
    key: 'destroy',
    value: function destroy() {
      this.ghostTable.clean();
      _get(AutoRowSize.prototype.__proto__ || Object.getPrototypeOf(AutoRowSize.prototype), 'destroy', this).call(this);
    }
  }]);

  return AutoRowSize;
}(_base2.default);

(0, _plugins.registerPlugin)('autoRowSize', AutoRowSize);

exports.default = AutoRowSize;

/***/ }),
/* 337 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


exports.__esModule = true;

var _createClass = 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); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

var _get = function get(object, property, receiver) { if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ("value" in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } };

var _base = __webpack_require__(16);

var _base2 = _interopRequireDefault(_base);

var _pluginHooks = __webpack_require__(11);

var _pluginHooks2 = _interopRequireDefault(_pluginHooks);

var _element = __webpack_require__(0);

var _eventManager = __webpack_require__(4);

var _eventManager2 = _interopRequireDefault(_eventManager);

var _plugins = __webpack_require__(9);

var _src = __webpack_require__(14);

var _utils = __webpack_require__(338);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }

function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }

_pluginHooks2.default.getSingleton().register('modifyAutofillRange');
_pluginHooks2.default.getSingleton().register('beforeAutofill');

var INSERT_ROW_ALTER_ACTION_NAME = 'insert_row';
var INSERT_COLUMN_ALTER_ACTION_NAME = 'insert_col';
var INTERVAL_FOR_ADDING_ROW = 200;

/**
 * This plugin provides "drag-down" and "copy-down" functionalities, both operated
 * using the small square in the right bottom of the cell selection.
 *
 * "Drag-down" expands the value of the selected cells to the neighbouring
 * cells when you drag the small square in the corner.
 *
 * "Copy-down" copies the value of the selection to all empty cells
 * below when you double click the small square.
 *
 * @class Autofill
 * @plugin Autofill
 */

var Autofill = function (_BasePlugin) {
  _inherits(Autofill, _BasePlugin);

  function Autofill(hotInstance) {
    _classCallCheck(this, Autofill);

    /**
     * Event manager
     *
     * @type {EventManager}
     */
    var _this = _possibleConstructorReturn(this, (Autofill.__proto__ || Object.getPrototypeOf(Autofill)).call(this, hotInstance));

    _this.eventManager = new _eventManager2.default(_this);
    /**
     * Specifies if adding new row started.
     *
     * @type {Boolean}
     */
    _this.addingStarted = false;
    /**
     * Specifies if there was mouse down on the cell corner.
     *
     * @type {Boolean}
     */
    _this.mouseDownOnCellCorner = false;
    /**
     * Specifies if mouse was dragged outside Handsontable.
     *
     * @type {Boolean}
     */
    _this.mouseDragOutside = false;
    /**
     * Specifies how many cell levels were dragged using the handle.
     *
     * @type {Boolean}
     */
    _this.handleDraggedCells = 0;
    /**
     * Specifies allowed directions of drag.
     *
     * @type {Array}
     */
    _this.directions = [];
    /**
     * Specifies if can insert new rows if needed.
     *
     * @type {Boolean}
     */
    _this.autoInsertRow = false;
    return _this;
  }

  /**
   * Check if the plugin is enabled in the Handsontable settings.
   *
   * @returns {Boolean}
   */


  _createClass(Autofill, [{
    key: 'isEnabled',
    value: function isEnabled() {
      return this.hot.getSettings().fillHandle;
    }

    /**
     * Enable plugin for this Handsontable instance.
     */

  }, {
    key: 'enablePlugin',
    value: function enablePlugin() {
      var _this2 = this;

      if (this.enabled) {
        return;
      }

      this.mapSettings();
      this.registerEvents();

      this.addHook('afterOnCellCornerMouseDown', function (event) {
        return _this2.onAfterCellCornerMouseDown(event);
      });
      this.addHook('afterOnCellCornerDblClick', function (event) {
        return _this2.onCellCornerDblClick(event);
      });
      this.addHook('beforeOnCellMouseOver', function (event, coords, TD) {
        return _this2.onBeforeCellMouseOver(coords);
      });

      _get(Autofill.prototype.__proto__ || Object.getPrototypeOf(Autofill.prototype), 'enablePlugin', this).call(this);
    }

    /**
     * Update plugin for this Handsontable instance.
     */

  }, {
    key: 'updatePlugin',
    value: function updatePlugin() {
      this.disablePlugin();
      this.enablePlugin();
      _get(Autofill.prototype.__proto__ || Object.getPrototypeOf(Autofill.prototype), 'updatePlugin', this).call(this);
    }

    /**
     * Disable plugin for this Handsontable instance.
     */

  }, {
    key: 'disablePlugin',
    value: function disablePlugin() {
      this.clearMappedSettings();
      _get(Autofill.prototype.__proto__ || Object.getPrototypeOf(Autofill.prototype), 'disablePlugin', this).call(this);
    }

    /**
     * Get selection data
     *
     * @private
     * @returns {Array} Array with the data.
     */

  }, {
    key: 'getSelectionData',
    value: function getSelectionData() {
      var selRange = {
        from: this.hot.getSelectedRange().from,
        to: this.hot.getSelectedRange().to
      };

      return this.hot.getData(selRange.from.row, selRange.from.col, selRange.to.row, selRange.to.col);
    }

    /**
     * Try to apply fill values to the area in fill border, omitting the selection border.
     *
     * @private
     * @returns {Boolean} reports if fill was applied.
     */

  }, {
    key: 'fillIn',
    value: function fillIn() {
      if (this.hot.view.wt.selections.fill.isEmpty()) {
        return false;
      }

      var cornersOfSelectionAndDragAreas = this.hot.view.wt.selections.fill.getCorners();

      this.resetSelectionOfDraggedArea();

      var cornersOfSelectedCells = this.getCornersOfSelectedCells();

      var _getDragDirectionAndR = (0, _utils.getDragDirectionAndRange)(cornersOfSelectedCells, cornersOfSelectionAndDragAreas),
          directionOfDrag = _getDragDirectionAndR.directionOfDrag,
          startOfDragCoords = _getDragDirectionAndR.startOfDragCoords,
          endOfDragCoords = _getDragDirectionAndR.endOfDragCoords;

      this.hot.runHooks('modifyAutofillRange', cornersOfSelectedCells, cornersOfSelectionAndDragAreas);

      if (startOfDragCoords && startOfDragCoords.row > -1 && startOfDragCoords.col > -1) {
        var selectionData = this.getSelectionData();
        var deltas = (0, _utils.getDeltas)(startOfDragCoords, endOfDragCoords, selectionData, directionOfDrag);
        var fillData = selectionData;

        this.hot.runHooks('beforeAutofill', startOfDragCoords, endOfDragCoords, selectionData);

        if (['up', 'left'].indexOf(directionOfDrag) > -1) {
          fillData = [];

          var dragLength = null;
          var fillOffset = null;

          if (directionOfDrag === 'up') {
            dragLength = endOfDragCoords.row - startOfDragCoords.row + 1;
            fillOffset = dragLength % selectionData.length;

            for (var i = 0; i < dragLength; i++) {
              fillData.push(selectionData[(i + (selectionData.length - fillOffset)) % selectionData.length]);
            }
          } else {
            dragLength = endOfDragCoords.col - startOfDragCoords.col + 1;
            fillOffset = dragLength % selectionData[0].length;

            for (var _i = 0; _i < selectionData.length; _i++) {
              fillData.push([]);
              for (var j = 0; j < dragLength; j++) {
                fillData[_i].push(selectionData[_i][(j + (selectionData[_i].length - fillOffset)) % selectionData[_i].length]);
              }
            }
          }
        }

        this.hot.populateFromArray(startOfDragCoords.row, startOfDragCoords.col, fillData, endOfDragCoords.row, endOfDragCoords.col, this.pluginName + '.fill', null, directionOfDrag, deltas);

        this.setSelection(cornersOfSelectionAndDragAreas);
      } else {
        // reset to avoid some range bug
        this.hot.selection.refreshBorders();
      }

      return true;
    }

    /**
     * Reduce the selection area if the handle was dragged outside of the table or on headers.
     *
     * @private
     * @param {CellCoords} coords indexes of selection corners.
     * @returns {CellCoords}
     */

  }, {
    key: 'reduceSelectionAreaIfNeeded',
    value: function reduceSelectionAreaIfNeeded(coords) {
      if (coords.row < 0) {
        coords.row = 0;
      }

      if (coords.col < 0) {
        coords.col = 0;
      }
      return coords;
    }

    /**
     * Get the coordinates of the drag & drop borders.
     *
     * @private
     * @param {CellCoords} coordsOfSelection `CellCoords` coord object.
     * @returns {Array}
     */

  }, {
    key: 'getCoordsOfDragAndDropBorders',
    value: function getCoordsOfDragAndDropBorders(coordsOfSelection) {
      var topLeftCorner = this.hot.getSelectedRange().getTopLeftCorner();
      var bottomRightCorner = this.hot.getSelectedRange().getBottomRightCorner();
      var coords = void 0;

      if (this.directions.includes(_utils.DIRECTIONS.vertical) && (bottomRightCorner.row < coordsOfSelection.row || topLeftCorner.row > coordsOfSelection.row)) {
        coords = new _src.CellCoords(coordsOfSelection.row, bottomRightCorner.col);
      } else if (this.directions.includes(_utils.DIRECTIONS.horizontal)) {
        coords = new _src.CellCoords(bottomRightCorner.row, coordsOfSelection.col);
      } else {
        // wrong direction
        return;
      }

      return this.reduceSelectionAreaIfNeeded(coords);
    }

    /**
     * Show the fill border.
     *
     * @private
     * @param {CellCoords} coordsOfSelection `CellCoords` coord object.
     */

  }, {
    key: 'showBorder',
    value: function showBorder(coordsOfSelection) {
      var coordsOfDragAndDropBorders = this.getCoordsOfDragAndDropBorders(coordsOfSelection);

      if (coordsOfDragAndDropBorders) {
        this.redrawBorders(coordsOfDragAndDropBorders);
      }
    }

    /**
     * Add new row
     *
     * @private
     */

  }, {
    key: 'addRow',
    value: function addRow() {
      var _this3 = this;

      this.hot._registerTimeout(setTimeout(function () {
        _this3.hot.alter(INSERT_ROW_ALTER_ACTION_NAME, void 0, 1, _this3.pluginName + '.fill');

        _this3.addingStarted = false;
      }, INTERVAL_FOR_ADDING_ROW));
    }

    /**
     * Add new row
     *
     * Added By COSMOCODE
     *
     * @private
     */

  }, {
    key: 'addColumn',
    value: function addColumn() {
      var _this4 = this;

      this.hot._registerTimeout(setTimeout(function () {
        _this4.hot.alter(INSERT_COLUMN_ALTER_ACTION_NAME, void 0, 1, _this4.pluginName + '.fill');

        _this4.addingStarted = false;
      }, INTERVAL_FOR_ADDING_ROW));
    }

    /**
     * Add new rows if they are needed to continue auto-filling values.
     *
     * @private
     */

  }, {
    key: 'addNewRowIfNeeded',
    value: function addNewRowIfNeeded() {
      if (this.hot.view.wt.selections.fill.cellRange && this.addingStarted === false && this.autoInsertRow) {
        var cornersOfSelectedCells = this.hot.getSelected();
        var cornersOfSelectedDragArea = this.hot.view.wt.selections.fill.getCorners();
        var nrOfTableRows = this.hot.countRows();

        if (cornersOfSelectedCells[2] < nrOfTableRows - 1 && cornersOfSelectedDragArea[2] === nrOfTableRows - 1) {
          this.addingStarted = true;

          this.addRow();
        }
      }
    }

    /**
     * Add new rows if they are needed to continue auto-filling values.
     *
     * Added By COSMOCODE
     *
     * @private
     */

  }, {
    key: 'addNewColumnIfNeeded',
    value: function addNewColumnIfNeeded() {
      if (this.hot.view.wt.selections.fill.cellRange && this.addingStarted === false && this.autoInsertRow) {
        var cornersOfSelectedCells = this.hot.getSelected();
        var cornersOfSelectedDragArea = this.hot.view.wt.selections.fill.getCorners();
        var nrOfTableCols = this.hot.countCols();

        if (cornersOfSelectedCells[3] < nrOfTableCols - 1 && cornersOfSelectedDragArea[3] === nrOfTableCols - 1) {
          this.addingStarted = true;

          this.addColumn();
        }
      }
    }

    /**
     * Get corners of selected cells.
     *
     * @private
     * @returns {Array}
     */

  }, {
    key: 'getCornersOfSelectedCells',
    value: function getCornersOfSelectedCells() {
      if (this.hot.selection.isMultiple()) {
        return this.hot.view.wt.selections.area.getCorners();
      }
      return this.hot.view.wt.selections.current.getCorners();
    }

    /**
     * Get index of last adjacent filled in row
     *
     * @private
     * @param {Array} cornersOfSelectedCells indexes of selection corners.
     * @returns {Number} gives number greater than or equal to zero when selection adjacent can be applied.
     * or -1 when selection adjacent can't be applied
     */

  }, {
    key: 'getIndexOfLastAdjacentFilledInRow',
    value: function getIndexOfLastAdjacentFilledInRow(cornersOfSelectedCells) {
      var data = this.hot.getData();
      var nrOfTableRows = this.hot.countRows();
      var lastFilledInRowIndex = void 0;

      for (var rowIndex = cornersOfSelectedCells[2] + 1; rowIndex < nrOfTableRows; rowIndex++) {
        for (var columnIndex = cornersOfSelectedCells[1]; columnIndex <= cornersOfSelectedCells[3]; columnIndex++) {
          var dataInCell = data[rowIndex][columnIndex];

          if (dataInCell) {
            return -1;
          }
        }

        var dataInNextLeftCell = data[rowIndex][cornersOfSelectedCells[1] - 1];
        var dataInNextRightCell = data[rowIndex][cornersOfSelectedCells[3] + 1];

        if (!!dataInNextLeftCell || !!dataInNextRightCell) {
          lastFilledInRowIndex = rowIndex;
        }
      }
      return lastFilledInRowIndex;
    }

    /**
     * Add a selection from the start area to the specific row index.
     *
     * @private
     * @param {Array} selectStartArea selection area from which we start to create more comprehensive selection.
     * @param {Number} rowIndex
     */

  }, {
    key: 'addSelectionFromStartAreaToSpecificRowIndex',
    value: function addSelectionFromStartAreaToSpecificRowIndex(selectStartArea, rowIndex) {
      this.hot.view.wt.selections.fill.clear();
      this.hot.view.wt.selections.fill.add(new _src.CellCoords(selectStartArea[0], selectStartArea[1]));
      this.hot.view.wt.selections.fill.add(new _src.CellCoords(rowIndex, selectStartArea[3]));
    }

    /**
     * Set selection based on passed corners.
     *
     * @private
     * @param {Array} cornersOfArea
     */

  }, {
    key: 'setSelection',
    value: function setSelection(cornersOfArea) {
      this.hot.selection.setRangeStart(new _src.CellCoords(cornersOfArea[0], cornersOfArea[1]));
      this.hot.selection.setRangeEnd(new _src.CellCoords(cornersOfArea[2], cornersOfArea[3]));
    }

    /**
     * Try to select cells down to the last row in the left column and then returns if selection was applied.
     *
     * @private
     * @returns {Boolean}
     */

  }, {
    key: 'selectAdjacent',
    value: function selectAdjacent() {
      var cornersOfSelectedCells = this.getCornersOfSelectedCells();
      var lastFilledInRowIndex = this.getIndexOfLastAdjacentFilledInRow(cornersOfSelectedCells);

      if (lastFilledInRowIndex === -1) {
        return false;
      }
      this.addSelectionFromStartAreaToSpecificRowIndex(cornersOfSelectedCells, lastFilledInRowIndex);

      return true;
    }

    /**
     * Reset selection of dragged area.
     *
     * @private
     */

  }, {
    key: 'resetSelectionOfDraggedArea',
    value: function resetSelectionOfDraggedArea() {
      this.handleDraggedCells = 0;

      this.hot.view.wt.selections.fill.clear();
    }

    /**
     * Redraw borders.
     *
     * @private
     * @param {CellCoords} coords `CellCoords` coord object.
     */

  }, {
    key: 'redrawBorders',
    value: function redrawBorders(coords) {
      this.hot.view.wt.selections.fill.clear();
      this.hot.view.wt.selections.fill.add(this.hot.getSelectedRange().from);
      this.hot.view.wt.selections.fill.add(this.hot.getSelectedRange().to);
      this.hot.view.wt.selections.fill.add(coords);
      this.hot.view.render();
    }

    /**
     * Get if mouse was dragged outside.
     *
     * @private
     * @param {MouseEvent} event `mousemove` event properties.
     * @returns {Boolean}
     */

  }, {
    key: 'getIfMouseWasDraggedOutside',
    value: function getIfMouseWasDraggedOutside(event) {
      var tableBottom = (0, _element.offset)(this.hot.table).top - (window.pageYOffset || document.documentElement.scrollTop) + (0, _element.outerHeight)(this.hot.table);
      var tableRight = (0, _element.offset)(this.hot.table).left - (window.pageXOffset || document.documentElement.scrollLeft) + (0, _element.outerWidth)(this.hot.table);

      return event.clientY > tableBottom && event.clientX <= tableRight;
    }

    /**
     * Bind the events used by the plugin.
     *
     * @private
     */

  }, {
    key: 'registerEvents',
    value: function registerEvents() {
      var _this5 = this;

      this.eventManager.addEventListener(document.documentElement, 'mouseup', function () {
        return _this5.onMouseUp();
      });
      this.eventManager.addEventListener(document.documentElement, 'mousemove', function (event) {
        return _this5.onMouseMove(event);
      });
    }

    /**
     * On cell corner double click callback.
     *
     * @private
     */

  }, {
    key: 'onCellCornerDblClick',
    value: function onCellCornerDblClick() {
      var selectionApplied = this.selectAdjacent();

      if (selectionApplied) {
        this.fillIn();
      }
    }

    /**
     * On after cell corner mouse down listener.
     *
     * @private
     */

  }, {
    key: 'onAfterCellCornerMouseDown',
    value: function onAfterCellCornerMouseDown() {
      this.handleDraggedCells = 1;
      this.mouseDownOnCellCorner = true;
    }

    /**
     * On before cell mouse over listener.
     *
     * @private
     * @param {CellCoords} coords `CellCoords` coord object.
     */

  }, {
    key: 'onBeforeCellMouseOver',
    value: function onBeforeCellMouseOver(coords) {
      if (this.mouseDownOnCellCorner && !this.hot.view.isMouseDown() && this.handleDraggedCells) {
        this.handleDraggedCells++;

        this.showBorder(coords);
        this.addNewRowIfNeeded();
        this.addNewColumnIfNeeded(); // COSMOCODE
      }
    }

    /**
     * On mouse up listener.
     *
     * @private
     */

  }, {
    key: 'onMouseUp',
    value: function onMouseUp() {
      if (this.handleDraggedCells) {
        if (this.handleDraggedCells > 1) {
          this.fillIn();
        }

        this.handleDraggedCells = 0;
        this.mouseDownOnCellCorner = false;
      }
    }

    /**
     * On mouse move listener.
     *
     * @private
     * @param {MouseEvent} event `mousemove` event properties.
     */

  }, {
    key: 'onMouseMove',
    value: function onMouseMove(event) {
      var mouseWasDraggedOutside = this.getIfMouseWasDraggedOutside(event);

      if (this.addingStarted === false && this.handleDraggedCells > 0 && mouseWasDraggedOutside) {
        this.mouseDragOutside = true;
        this.addingStarted = true;
      } else {
        this.mouseDragOutside = false;
      }

      if (this.mouseDragOutside && this.autoInsertRow) {
        this.addRow();
      }
    }

    /**
     * Clear mapped settings.
     *
     * @private
     */

  }, {
    key: 'clearMappedSettings',
    value: function clearMappedSettings() {
      this.directions.length = 0;
      this.autoInsertRow = false;
    }

    /**
     * Map settings.
     *
     * @private
     */

  }, {
    key: 'mapSettings',
    value: function mapSettings() {
      var mappedSettings = (0, _utils.getMappedFillHandleSetting)(this.hot.getSettings().fillHandle);
      this.directions = mappedSettings.directions;
      this.autoInsertRow = mappedSettings.autoInsertRow;
    }

    /**
     * Destroy plugin instance.
     */

  }, {
    key: 'destroy',
    value: function destroy() {
      _get(Autofill.prototype.__proto__ || Object.getPrototypeOf(Autofill.prototype), 'destroy', this).call(this);
    }
  }]);

  return Autofill;
}(_base2.default);

(0, _plugins.registerPlugin)('autofill', Autofill);

exports.default = Autofill;

/***/ }),
/* 338 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


exports.__esModule = true;
exports.DIRECTIONS = undefined;
exports.getDeltas = getDeltas;
exports.getDragDirectionAndRange = getDragDirectionAndRange;
exports.getMappedFillHandleSetting = getMappedFillHandleSetting;

var _object = __webpack_require__(3);

var _mixed = __webpack_require__(23);

var _src = __webpack_require__(14);

var DIRECTIONS = exports.DIRECTIONS = {
  horizontal: 'horizontal',
  vertical: 'vertical'
};

/**
 * Get deltas array.
 *
 * @param {CellCoords} start
 * @param {CellCoords} end
 * @param {Array} data
 * @param {String} direction
 * @returns {Array}
 */
function getDeltas(start, end, data, direction) {
  var rowsLength = data.length;
  var columnsLength = data ? data[0].length : 0;
  var deltas = [];
  var diffRow = end.row - start.row;
  var diffCol = end.col - start.col;

  if (['down', 'up'].indexOf(direction) !== -1) {
    var arr = [];

    for (var col = 0; col <= diffCol; col++) {
      var startValue = parseInt(data[0][col], 10);
      var endValue = parseInt(data[rowsLength - 1][col], 10);
      var delta = (direction === 'down' ? endValue - startValue : startValue - endValue) / (rowsLength - 1) || 0;

      arr.push(delta);
    }

    deltas.push(arr);
  }

  if (['right', 'left'].indexOf(direction) !== -1) {
    for (var row = 0; row <= diffRow; row++) {
      var _startValue = parseInt(data[row][0], 10);
      var _endValue = parseInt(data[row][columnsLength - 1], 10);
      var _delta = (direction === 'right' ? _endValue - _startValue : _startValue - _endValue) / (columnsLength - 1) || 0;

      deltas.push([_delta]);
    }
  }

  return deltas;
}

/**
 * Get direction between positions and cords of selections difference (drag area)
 *
 * @param {Array} startSelection
 * @param {Array} endSelection
 * @returns {{direction: String, start: CellCoords, end: CellCoords}}
 */
function getDragDirectionAndRange(startSelection, endSelection) {
  var startOfDragCoords = void 0,
      endOfDragCoords = void 0,
      directionOfDrag = void 0;

  if (endSelection[0] === startSelection[0] && endSelection[1] < startSelection[1]) {
    directionOfDrag = 'left';

    startOfDragCoords = new _src.CellCoords(endSelection[0], endSelection[1]);
    endOfDragCoords = new _src.CellCoords(endSelection[2], startSelection[1] - 1);
  } else if (endSelection[0] === startSelection[0] && endSelection[3] > startSelection[3]) {
    directionOfDrag = 'right';

    startOfDragCoords = new _src.CellCoords(endSelection[0], startSelection[3] + 1);
    endOfDragCoords = new _src.CellCoords(endSelection[2], endSelection[3]);
  } else if (endSelection[0] < startSelection[0] && endSelection[1] === startSelection[1]) {
    directionOfDrag = 'up';

    startOfDragCoords = new _src.CellCoords(endSelection[0], endSelection[1]);
    endOfDragCoords = new _src.CellCoords(startSelection[0] - 1, endSelection[3]);
  } else if (endSelection[2] > startSelection[2] && endSelection[1] === startSelection[1]) {
    directionOfDrag = 'down';

    startOfDragCoords = new _src.CellCoords(startSelection[2] + 1, endSelection[1]);
    endOfDragCoords = new _src.CellCoords(endSelection[2], endSelection[3]);
  }

  return {
    directionOfDrag: directionOfDrag,
    startOfDragCoords: startOfDragCoords,
    endOfDragCoords: endOfDragCoords
  };
}

/**
 * Get mapped FillHandle setting containing information about
 * allowed FillHandle directions and if allowed is automatic insertion of rows on drag
 *
 * @param {Boolean|Object} fillHandle property of Handsontable settings
 * @returns {{directions: Array, autoInsertRow: Boolean}} object allowing access to information
 * about FillHandle in more useful way
 */
function getMappedFillHandleSetting(fillHandle) {
  var mappedSettings = {};

  if (fillHandle === true) {
    mappedSettings.directions = Object.keys(DIRECTIONS);
    mappedSettings.autoInsertRow = true;
  } else if ((0, _object.isObject)(fillHandle)) {
    if ((0, _mixed.isDefined)(fillHandle.autoInsertRow)) {

      // autoInsertRow for horizontal direction will be always false

      if (fillHandle.direction === DIRECTIONS.horizontal) {
        mappedSettings.autoInsertRow = false;
      } else {
        mappedSettings.autoInsertRow = fillHandle.autoInsertRow;
      }
    } else {
      mappedSettings.autoInsertRow = false;
    }

    if ((0, _mixed.isDefined)(fillHandle.direction)) {
      mappedSettings.directions = [fillHandle.direction];
    } else {
      mappedSettings.directions = Object.keys(DIRECTIONS);
    }
  } else if (typeof fillHandle === 'string') {
    mappedSettings.directions = [fillHandle];
    mappedSettings.autoInsertRow = true;
  } else {
    mappedSettings.directions = [];
    mappedSettings.autoInsertRow = false;
  }

  return mappedSettings;
}

/***/ }),
/* 339 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


exports.__esModule = true;

var _createClass = 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); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

var _array = __webpack_require__(2);

var _object = __webpack_require__(3);

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

/**
 * Command executor for ContextMenu.
 *
 * @class CommandExecutor
 * @plugin ContextMenu
 */
var CommandExecutor = function () {
  function CommandExecutor(hotInstance) {
    _classCallCheck(this, CommandExecutor);

    this.hot = hotInstance;
    this.commands = {};
    this.commonCallback = null;
  }

  /**
   * Register command.
   *
   * @param {String} name Command name.
   * @param {Object} commandDescriptor Command descriptor object with properties like `key` (command id),
   *                                   `callback` (task to execute), `name` (command name), `disabled` (command availability).
   */


  _createClass(CommandExecutor, [{
    key: 'registerCommand',
    value: function registerCommand(name, commandDescriptor) {
      this.commands[name] = commandDescriptor;
    }

    /**
     * Set common callback which will be trigger on every executed command.
     *
     * @param {Function} callback Function which will be fired on every command execute.
     */

  }, {
    key: 'setCommonCallback',
    value: function setCommonCallback(callback) {
      this.commonCallback = callback;
    }

    /**
     * Execute command by its name.
     *
     * @param {String} commandName Command id.
     * @param {*} params Arguments passed to command task.
     */

  }, {
    key: 'execute',
    value: function execute(commandName) {
      var _this = this;

      for (var _len = arguments.length, params = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
        params[_key - 1] = arguments[_key];
      }

      var commandSplit = commandName.split(':');
      commandName = commandSplit[0];

      var subCommandName = commandSplit.length === 2 ? commandSplit[1] : null;
      var command = this.commands[commandName];

      if (!command) {
        throw new Error('Menu command \'' + commandName + '\' not exists.');
      }
      if (subCommandName && command.submenu) {
        command = findSubCommand(subCommandName, command.submenu.items);
      }
      if (command.disabled === true) {
        return;
      }
      if (typeof command.disabled == 'function' && command.disabled.call(this.hot) === true) {
        return;
      }
      if ((0, _object.hasOwnProperty)(command, 'submenu')) {
        return;
      }
      var callbacks = [];

      if (typeof command.callback === 'function') {
        callbacks.push(command.callback);
      }
      if (typeof this.commonCallback === 'function') {
        callbacks.push(this.commonCallback);
      }
      params.unshift(commandSplit.join(':'));
      (0, _array.arrayEach)(callbacks, function (callback) {
        return callback.apply(_this.hot, params);
      });
    }
  }]);

  return CommandExecutor;
}();

function findSubCommand(subCommandName, subCommands) {
  var command = void 0;

  (0, _array.arrayEach)(subCommands, function (cmd) {
    var cmds = cmd.key ? cmd.key.split(':') : null;

    if (Array.isArray(cmds) && cmds[1] === subCommandName) {
      command = cmd;

      return false;
    }
  });

  return command;
}

exports.default = CommandExecutor;

/***/ }),
/* 340 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


exports.__esModule = true;

var _get = function get(object, property, receiver) { if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ("value" in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } };

var _createClass = 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); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

var _base = __webpack_require__(16);

var _base2 = _interopRequireDefault(_base);

var _pluginHooks = __webpack_require__(11);

var _pluginHooks2 = _interopRequireDefault(_pluginHooks);

var _array = __webpack_require__(2);

var _commandExecutor = __webpack_require__(339);

var _commandExecutor2 = _interopRequireDefault(_commandExecutor);

var _eventManager = __webpack_require__(4);

var _eventManager2 = _interopRequireDefault(_eventManager);

var _itemsFactory = __webpack_require__(342);

var _itemsFactory2 = _interopRequireDefault(_itemsFactory);

var _menu = __webpack_require__(343);

var _menu2 = _interopRequireDefault(_menu);

var _plugins = __webpack_require__(9);

var _event = __webpack_require__(7);

var _element = __webpack_require__(0);

var _predefinedItems = __webpack_require__(72);

__webpack_require__(299);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }

function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }

_pluginHooks2.default.getSingleton().register('afterContextMenuDefaultOptions');
_pluginHooks2.default.getSingleton().register('afterContextMenuShow');
_pluginHooks2.default.getSingleton().register('afterContextMenuHide');
_pluginHooks2.default.getSingleton().register('afterContextMenuExecute');

/**
 * @description
 * This plugin creates the Handsontable Context Menu. It allows to create a new row or
 * column at any place in the grid among [other features](http://docs.handsontable.com/demo-context-menu.html).
 * Possible values:
 * * `true` (to enable default options),
 * * `false` (to disable completely)
 *
 * or array of any available strings:
 * * `["row_above", "row_below", "col_left", "col_right",
 * "remove_row", "remove_col", "---------", "undo", "redo"]`.
 *
 * See [the context menu demo](http://docs.handsontable.com/demo-context-menu.html) for examples.
 *
 * @example
 * ```js
 * ...
 * // as a boolean
 * contextMenu: true
 * ...
 * // as a array
 * contextMenu: ['row_above', 'row_below', '---------', 'undo', 'redo']
 * ...
 * ```
 *
 * @plugin ContextMenu
 */

var ContextMenu = function (_BasePlugin) {
  _inherits(ContextMenu, _BasePlugin);

  _createClass(ContextMenu, null, [{
    key: 'DEFAULT_ITEMS',

    /**
     * Default menu items order when `contextMenu` is enabled by `true`.
     *
     * @returns {Array}
     */
    get: function get() {
      return [_predefinedItems.ROW_ABOVE, _predefinedItems.ROW_BELOW, _predefinedItems.SEPARATOR, _predefinedItems.COLUMN_LEFT, _predefinedItems.COLUMN_RIGHT, _predefinedItems.SEPARATOR, _predefinedItems.REMOVE_ROW, _predefinedItems.REMOVE_COLUMN, _predefinedItems.SEPARATOR, _predefinedItems.UNDO, _predefinedItems.REDO, _predefinedItems.SEPARATOR, _predefinedItems.READ_ONLY, _predefinedItems.SEPARATOR, _predefinedItems.ALIGNMENT];
    }
  }]);

  function ContextMenu(hotInstance) {
    _classCallCheck(this, ContextMenu);

    /**
     * Instance of {@link EventManager}.
     *
     * @type {EventManager}
     */
    var _this = _possibleConstructorReturn(this, (ContextMenu.__proto__ || Object.getPrototypeOf(ContextMenu)).call(this, hotInstance));

    _this.eventManager = new _eventManager2.default(_this);
    /**
     * Instance of {@link CommandExecutor}.
     *
     * @type {CommandExecutor}
     */
    _this.commandExecutor = new _commandExecutor2.default(_this.hot);
    /**
     * Instance of {@link ItemsFactory}.
     *
     * @type {ItemsFactory}
     */
    _this.itemsFactory = null;
    /**
     * Instance of {@link Menu}.
     *
     * @type {Menu}
     */
    _this.menu = null;
    return _this;
  }

  /**
   * Check if the plugin is enabled in the Handsontable settings.
   *
   * @returns {Boolean}
   */


  _createClass(ContextMenu, [{
    key: 'isEnabled',
    value: function isEnabled() {
      return this.hot.getSettings().contextMenu;
    }

    /**
     * Enable plugin for this Handsontable instance.
     */

  }, {
    key: 'enablePlugin',
    value: function enablePlugin() {
      var _this2 = this;

      if (this.enabled) {
        return;
      }
      this.itemsFactory = new _itemsFactory2.default(this.hot, ContextMenu.DEFAULT_ITEMS);

      var settings = this.hot.getSettings().contextMenu;
      var predefinedItems = {
        items: this.itemsFactory.getItems(settings)
      };
      this.registerEvents();

      if (typeof settings.callback === 'function') {
        this.commandExecutor.setCommonCallback(settings.callback);
      }
      _get(ContextMenu.prototype.__proto__ || Object.getPrototypeOf(ContextMenu.prototype), 'enablePlugin', this).call(this);

      this.callOnPluginsReady(function () {
        _this2.hot.runHooks('afterContextMenuDefaultOptions', predefinedItems);

        _this2.itemsFactory.setPredefinedItems(predefinedItems.items);
        var menuItems = _this2.itemsFactory.getItems(settings);

        _this2.menu = new _menu2.default(_this2.hot, {
          className: 'htContextMenu',
          keepInViewport: true
        });
        _this2.hot.runHooks('beforeContextMenuSetItems', menuItems);

        _this2.menu.setMenuItems(menuItems);

        _this2.menu.addLocalHook('afterOpen', function () {
          return _this2.onMenuAfterOpen();
        });
        _this2.menu.addLocalHook('afterClose', function () {
          return _this2.onMenuAfterClose();
        });
        _this2.menu.addLocalHook('executeCommand', function () {
          for (var _len = arguments.length, params = Array(_len), _key = 0; _key < _len; _key++) {
            params[_key] = arguments[_key];
          }

          return _this2.executeCommand.apply(_this2, params);
        });

        // Register all commands. Predefined and added by user or by plugins
        (0, _array.arrayEach)(menuItems, function (command) {
          return _this2.commandExecutor.registerCommand(command.key, command);
        });
      });
    }

    /**
     * Updates the plugin to use the latest options you have specified.
     */

  }, {
    key: 'updatePlugin',
    value: function updatePlugin() {
      this.disablePlugin();
      this.enablePlugin();

      _get(ContextMenu.prototype.__proto__ || Object.getPrototypeOf(ContextMenu.prototype), 'updatePlugin', this).call(this);
    }

    /**
     * Disable plugin for this Handsontable instance.
     */

  }, {
    key: 'disablePlugin',
    value: function disablePlugin() {
      this.close();

      if (this.menu) {
        this.menu.destroy();
        this.menu = null;
      }
      _get(ContextMenu.prototype.__proto__ || Object.getPrototypeOf(ContextMenu.prototype), 'disablePlugin', this).call(this);
    }

    /**
     * Register dom listeners.
     *
     * @private
     */

  }, {
    key: 'registerEvents',
    value: function registerEvents() {
      var _this3 = this;

      this.eventManager.addEventListener(this.hot.rootElement, 'contextmenu', function (event) {
        return _this3.onContextMenu(event);
      });
    }

    /**
     * Open menu and re-position it based on dom event object.
     *
     * @param {Event} event The event object.
     */

  }, {
    key: 'open',
    value: function open(event) {
      if (!this.menu) {
        return;
      }
      this.menu.open();
      this.menu.setPosition({
        top: parseInt((0, _event.pageY)(event), 10) - (0, _element.getWindowScrollTop)(),
        left: parseInt((0, _event.pageX)(event), 10) - (0, _element.getWindowScrollLeft)()
      });

      // ContextMenu is not detected HotTableEnv correctly because is injected outside hot-table
      this.menu.hotMenu.isHotTableEnv = this.hot.isHotTableEnv;
      // Handsontable.eventManager.isHotTableEnv = this.hot.isHotTableEnv;
    }

    /**
     * Close menu.
     */

  }, {
    key: 'close',
    value: function close() {
      if (!this.menu) {
        return;
      }
      this.menu.close();
    }

    /**
     * Execute context menu command.
     *
     * You can execute all predefined commands:
     *  * `'row_above'` - Insert row above
     *  * `'row_below'` - Insert row below
     *  * `'col_left'` - Insert column on the left
     *  * `'col_right'` - Insert column on the right
     *  * `'clear_column'` - Clear selected column
     *  * `'remove_row'` - Remove row
     *  * `'remove_col'` - Remove column
     *  * `'undo'` - Undo last action
     *  * `'redo'` - Redo last action
     *  * `'make_read_only'` - Make cell read only
     *  * `'alignment:left'` - Alignment to the left
     *  * `'alignment:top'` - Alignment to the top
     *  * `'alignment:right'` - Alignment to the right
     *  * `'alignment:bottom'` - Alignment to the bottom
     *  * `'alignment:middle'` - Alignment to the middle
     *  * `'alignment:center'` - Alignment to the center (justify)
     *
     * Or you can execute command registered in settings where `key` is your command name.
     *
     * @param {String} commandName
     * @param {*} params
     */

  }, {
    key: 'executeCommand',
    value: function executeCommand() {
      for (var _len2 = arguments.length, params = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
        params[_key2] = arguments[_key2];
      }

      this.commandExecutor.execute.apply(this.commandExecutor, params);
    }

    /**
     * On context menu listener.
     *
     * @private
     * @param {Event} event
     */

  }, {
    key: 'onContextMenu',
    value: function onContextMenu(event) {
      var settings = this.hot.getSettings();
      var showRowHeaders = settings.rowHeaders;
      var showColHeaders = settings.colHeaders;

      function isValidElement(element) {
        return element.nodeName === 'TD' || element.parentNode.nodeName === 'TD';
      }
      // if event is from hot-table we must get web component element not element inside him
      var element = event.realTarget;
      this.close();

      if ((0, _element.hasClass)(element, 'handsontableInput')) {
        return;
      }

      event.preventDefault();
      (0, _event.stopPropagation)(event);

      if (!(showRowHeaders || showColHeaders)) {
        if (!isValidElement(element) && !((0, _element.hasClass)(element, 'current') && (0, _element.hasClass)(element, 'wtBorder'))) {
          return;
        }
      }

      this.open(event);
    }

    /**
     * On menu after open listener.
     *
     * @private
     */

  }, {
    key: 'onMenuAfterOpen',
    value: function onMenuAfterOpen() {
      this.hot.runHooks('afterContextMenuShow', this);
    }

    /**
     * On menu after close listener.
     *
     * @private
     */

  }, {
    key: 'onMenuAfterClose',
    value: function onMenuAfterClose() {
      this.hot.listen();
      this.hot.runHooks('afterContextMenuHide', this);
    }

    /**
     * Destroy instance.
     */

  }, {
    key: 'destroy',
    value: function destroy() {
      this.close();

      if (this.menu) {
        this.menu.destroy();
      }
      _get(ContextMenu.prototype.__proto__ || Object.getPrototypeOf(ContextMenu.prototype), 'destroy', this).call(this);
    }
  }]);

  return ContextMenu;
}(_base2.default);

ContextMenu.SEPARATOR = {
  name: _predefinedItems.SEPARATOR
};

(0, _plugins.registerPlugin)('contextMenu', ContextMenu);

exports.default = ContextMenu;

/***/ }),
/* 341 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


exports.__esModule = true;

var _createClass = 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); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

var _element = __webpack_require__(0);

var _event = __webpack_require__(7);

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

/**
 * Helper class for checking if element will fit at the desired side of cursor.
 *
 * @class Cursor
 * @plugin ContextMenu
 */
var Cursor = function () {
  function Cursor(object) {
    _classCallCheck(this, Cursor);

    var windowScrollTop = (0, _element.getWindowScrollTop)();
    var windowScrollLeft = (0, _element.getWindowScrollLeft)();
    var top = void 0,
        topRelative = void 0;
    var left = void 0,
        leftRelative = void 0;
    var cellHeight = void 0,
        cellWidth = void 0;

    this.type = this.getSourceType(object);

    if (this.type === 'literal') {
      top = parseInt(object.top, 10);
      left = parseInt(object.left, 10);
      cellHeight = object.height || 0;
      cellWidth = object.width || 0;
      topRelative = top;
      leftRelative = left;
      top += windowScrollTop;
      left += windowScrollLeft;
    } else if (this.type === 'event') {
      top = parseInt((0, _event.pageY)(object), 10);
      left = parseInt((0, _event.pageX)(object), 10);
      cellHeight = object.target.clientHeight;
      cellWidth = object.target.clientWidth;
      topRelative = top - windowScrollTop;
      leftRelative = left - windowScrollLeft;
    }

    this.top = top;
    this.topRelative = topRelative;
    this.left = left;
    this.leftRelative = leftRelative;
    this.scrollTop = windowScrollTop;
    this.scrollLeft = windowScrollLeft;
    this.cellHeight = cellHeight;
    this.cellWidth = cellWidth;
  }

  /**
   * Get source type name.
   *
   * @param {*} object Event or Object with coordinates.
   * @returns {String} Returns one of this values: `'literal'`, `'event'`.
   */


  _createClass(Cursor, [{
    key: 'getSourceType',
    value: function getSourceType(object) {
      var type = 'literal';

      if (object instanceof Event) {
        type = 'event';
      }

      return type;
    }

    /**
     * Checks if element can be placed above the cursor.
     *
     * @param {HTMLElement} element Element to check if it's size will fit above the cursor.
     * @returns {Boolean}
     */

  }, {
    key: 'fitsAbove',
    value: function fitsAbove(element) {
      return this.topRelative >= element.offsetHeight;
    }

    /**
     * Checks if element can be placed below the cursor.
     *
     * @param {HTMLElement} element Element to check if it's size will fit below the cursor.
     * @param {Number} [viewportHeight] The viewport height.
     * @returns {Boolean}
     */

  }, {
    key: 'fitsBelow',
    value: function fitsBelow(element) {
      var viewportHeight = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : window.innerHeight;

      return this.topRelative + element.offsetHeight <= viewportHeight;
    }

    /**
     * Checks if element can be placed on the right of the cursor.
     *
     * @param {HTMLElement} element Element to check if it's size will fit on the right of the cursor.
     * @param {Number} [viewportWidth] The viewport width.
     * @returns {Boolean}
     */

  }, {
    key: 'fitsOnRight',
    value: function fitsOnRight(element) {
      var viewportWidth = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : window.innerWidth;

      return this.leftRelative + this.cellWidth + element.offsetWidth <= viewportWidth;
    }

    /**
     * Checks if element can be placed on the left on the cursor.
     *
     * @param {HTMLElement} element Element to check if it's size will fit on the left of the cursor.
     * @returns {Boolean}
     */

  }, {
    key: 'fitsOnLeft',
    value: function fitsOnLeft(element) {
      return this.leftRelative >= element.offsetWidth;
    }
  }]);

  return Cursor;
}();

exports.default = Cursor;

/***/ }),
/* 342 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


exports.__esModule = true;

var _createClass = 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); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

var _object = __webpack_require__(3);

var _array = __webpack_require__(2);

var _predefinedItems = __webpack_require__(72);

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

/**
 * Predefined items class factory for menu items.
 *
 * @class ItemsFactory
 * @plugin ContextMenu
 */
var ItemsFactory = function () {
  function ItemsFactory(hotInstance) {
    var orderPattern = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;

    _classCallCheck(this, ItemsFactory);

    this.hot = hotInstance;
    this.predefinedItems = (0, _predefinedItems.predefinedItems)();
    this.defaultOrderPattern = orderPattern;
  }

  /**
   * Set predefined items.
   *
   * @param {Array} predefinedItems Array of predefined items.
   */


  _createClass(ItemsFactory, [{
    key: 'setPredefinedItems',
    value: function setPredefinedItems(predefinedItems) {
      var _this = this;

      var items = {};

      this.defaultOrderPattern.length = 0;

      (0, _object.objectEach)(predefinedItems, function (value, key) {
        var menuItemKey = '';

        if (value.name === _predefinedItems.SEPARATOR) {
          items[_predefinedItems.SEPARATOR] = value;
          menuItemKey = _predefinedItems.SEPARATOR;

          // Menu item added as a property to array
        } else if (isNaN(parseInt(key, 10))) {
          value.key = value.key === void 0 ? key : value.key;
          items[key] = value;
          menuItemKey = value.key;
        } else {
          items[value.key] = value;
          menuItemKey = value.key;
        }
        _this.defaultOrderPattern.push(menuItemKey);
      });
      this.predefinedItems = items;
    }

    /**
     * Get all menu items based on pattern.
     *
     * @param {Array|Object|Boolean} pattern Pattern which you can define by displaying menu items order. If `true` default
     *                                       pattern will be used.
     * @returns {Array}
     */

  }, {
    key: 'getItems',
    value: function getItems() {
      var pattern = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;

      return _getItems(pattern, this.defaultOrderPattern, this.predefinedItems);
    }
  }]);

  return ItemsFactory;
}();

function _getItems() {
  var pattern = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;
  var defaultPattern = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
  var items = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};

  var result = [];

  if (pattern && pattern.items) {
    pattern = pattern.items;
  } else if (!Array.isArray(pattern)) {
    pattern = defaultPattern;
  }
  if ((0, _object.isObject)(pattern)) {
    (0, _object.objectEach)(pattern, function (value, key) {
      var item = items[typeof value === 'string' ? value : key];

      if (!item) {
        item = value;
      }
      if ((0, _object.isObject)(value)) {
        (0, _object.extend)(item, value);
      } else if (typeof item === 'string') {
        item = { name: item };
      }
      if (item.key === void 0) {
        item.key = key;
      }
      result.push(item);
    });
  } else {
    (0, _array.arrayEach)(pattern, function (name, key) {
      var item = items[name];

      // Item deleted from settings `allowInsertRow: false` etc.
      if (!item && _predefinedItems.ITEMS.indexOf(name) >= 0) {
        return;
      }
      if (!item) {
        item = { name: name, key: '' + key };
      }
      if ((0, _object.isObject)(name)) {
        (0, _object.extend)(item, name);
      }
      if (item.key === void 0) {
        item.key = key;
      }
      result.push(item);
    });
  }

  return result;
}

exports.default = ItemsFactory;

/***/ }),
/* 343 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


exports.__esModule = true;

var _createClass = 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); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

var _core = __webpack_require__(66);

var _core2 = _interopRequireDefault(_core);

var _element = __webpack_require__(0);

var _array = __webpack_require__(2);

var _cursor = __webpack_require__(341);

var _cursor2 = _interopRequireDefault(_cursor);

var _eventManager = __webpack_require__(4);

var _eventManager2 = _interopRequireDefault(_eventManager);

var _object = __webpack_require__(3);

var _function = __webpack_require__(35);

var _utils = __webpack_require__(19);

var _unicode = __webpack_require__(15);

var _localHooks = __webpack_require__(333);

var _localHooks2 = _interopRequireDefault(_localHooks);

var _predefinedItems = __webpack_require__(72);

var _event = __webpack_require__(7);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

/**
 * @class Menu
 * @plugin ContextMenu
 */
var Menu = function () {
  function Menu(hotInstance, options) {
    _classCallCheck(this, Menu);

    this.hot = hotInstance;
    this.options = options || {
      parent: null,
      name: null,
      className: '',
      keepInViewport: true,
      standalone: false
    };
    this.eventManager = new _eventManager2.default(this);
    this.container = this.createContainer(this.options.name);
    this.hotMenu = null;
    this.hotSubMenus = {};
    this.parentMenu = this.options.parent || null;
    this.menuItems = null;
    this.origOutsideClickDeselects = null;
    this.keyEvent = false;

    this.offset = {
      above: 0,
      below: 0,
      left: 0,
      right: 0
    };
    this._afterScrollCallback = null;

    this.registerEvents();
  }

  /**
   * Register event listeners.
   *
   * @private
   */


  _createClass(Menu, [{
    key: 'registerEvents',
    value: function registerEvents() {
      var _this = this;

      this.eventManager.addEventListener(document.documentElement, 'mousedown', function (event) {
        return _this.onDocumentMouseDown(event);
      });
    }

    /**
     * Set array of objects which defines menu items.
     *
     * @param {Array} menuItems Menu items to display.
     */

  }, {
    key: 'setMenuItems',
    value: function setMenuItems(menuItems) {
      this.menuItems = menuItems;
    }

    /**
     * Set offset menu position for specified area (`above`, `below`, `left` or `right`).
     *
     * @param {String} area Specified area name (`above`, `below`, `left` or `right`).
     * @param {Number} offset Offset value.
     */

  }, {
    key: 'setOffset',
    value: function setOffset(area) {
      var offset = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;

      this.offset[area] = offset;
    }

    /**
     * Check if menu is using as sub-menu.
     *
     * @returns {Boolean}
     */

  }, {
    key: 'isSubMenu',
    value: function isSubMenu() {
      return this.parentMenu !== null;
    }

    /**
     * Open menu.
     */

  }, {
    key: 'open',
    value: function open() {
      var _this2 = this;

      this.container.removeAttribute('style');
      this.container.style.display = 'block';

      var delayedOpenSubMenu = (0, _function.debounce)(function (row) {
        return _this2.openSubMenu(row);
      }, 300);

      var filteredItems = (0, _array.arrayFilter)(this.menuItems, function (item) {
        return (0, _utils.isItemHidden)(item, _this2.hot);
      });

      filteredItems = (0, _utils.filterSeparators)(filteredItems, _predefinedItems.SEPARATOR);

      var settings = {
        data: filteredItems,
        colHeaders: false,
        colWidths: [200],
        autoRowSize: false,
        readOnly: true,
        copyPaste: false,
        columns: [{
          data: 'name',
          renderer: function renderer(hot, TD, row, col, prop, value) {
            return _this2.menuItemRenderer(hot, TD, row, col, prop, value);
          }
        }],
        renderAllRows: true,
        fragmentSelection: 'cell',
        disableVisualSelection: 'area',
        beforeKeyDown: function beforeKeyDown(event) {
          return _this2.onBeforeKeyDown(event);
        },
        afterOnCellMouseOver: function afterOnCellMouseOver(event, coords, TD) {
          if (_this2.isAllSubMenusClosed()) {
            delayedOpenSubMenu(coords.row);
          } else {
            _this2.openSubMenu(coords.row);
          }
        },
        rowHeights: function rowHeights(row) {
          return filteredItems[row].name === _predefinedItems.SEPARATOR ? 1 : 23;
        }
      };
      this.origOutsideClickDeselects = this.hot.getSettings().outsideClickDeselects;
      this.hot.getSettings().outsideClickDeselects = false;
      this.hotMenu = new _core2.default(this.container, settings);
      this.hotMenu.addHook('afterInit', function () {
        return _this2.onAfterInit();
      });
      this.hotMenu.addHook('afterSelection', function (r, c, r2, c2, preventScrolling) {
        return _this2.onAfterSelection(r, c, r2, c2, preventScrolling);
      });
      this.hotMenu.init();
      this.hotMenu.listen();
      this.blockMainTableCallbacks();
      this.runLocalHooks('afterOpen');
    }

    /**
     * Close menu.
     *
     * @param {Boolean} [closeParent=false] if `true` try to close parent menu if exists.
     */

  }, {
    key: 'close',
    value: function close() {
      var closeParent = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;

      if (!this.isOpened()) {
        return;
      }
      if (closeParent && this.parentMenu) {
        this.parentMenu.close();
      } else {
        this.closeAllSubMenus();
        this.container.style.display = 'none';
        this.releaseMainTableCallbacks();
        this.hotMenu.destroy();
        this.hotMenu = null;
        this.hot.getSettings().outsideClickDeselects = this.origOutsideClickDeselects;
        this.runLocalHooks('afterClose');

        if (this.parentMenu) {
          this.parentMenu.hotMenu.listen();
        }
      }
    }

    /**
     * Open sub menu at the provided row index.
     *
     * @param {Number} row Row index.
     * @returns {Menu|Boolean} Returns created menu or `false` if no one menu was created.
     */

  }, {
    key: 'openSubMenu',
    value: function openSubMenu(row) {
      if (!this.hotMenu) {
        return false;
      }
      var cell = this.hotMenu.getCell(row, 0);

      this.closeAllSubMenus();

      if (!cell || !(0, _utils.hasSubMenu)(cell)) {
        return false;
      }
      var dataItem = this.hotMenu.getSourceDataAtRow(row);
      var subMenu = new Menu(this.hot, {
        parent: this,
        name: dataItem.name,
        className: this.options.className,
        keepInViewport: true
      });
      subMenu.setMenuItems(dataItem.submenu.items);
      subMenu.open();
      subMenu.setPosition(cell.getBoundingClientRect());
      this.hotSubMenus[dataItem.key] = subMenu;

      return subMenu;
    }

    /**
     * Close sub menu at row index.
     *
     * @param {Number} row Row index.
     */

  }, {
    key: 'closeSubMenu',
    value: function closeSubMenu(row) {
      var dataItem = this.hotMenu.getSourceDataAtRow(row);
      var menus = this.hotSubMenus[dataItem.key];

      if (menus) {
        menus.destroy();
        delete this.hotSubMenus[dataItem.key];
      }
    }

    /**
     * Close all opened sub menus.
     */

  }, {
    key: 'closeAllSubMenus',
    value: function closeAllSubMenus() {
      var _this3 = this;

      (0, _array.arrayEach)(this.hotMenu.getData(), function (value, row) {
        return _this3.closeSubMenu(row);
      });
    }

    /**
     * Checks if all created and opened sub menus are closed.
     *
     * @returns {Boolean}
     */

  }, {
    key: 'isAllSubMenusClosed',
    value: function isAllSubMenusClosed() {
      return Object.keys(this.hotSubMenus).length === 0;
    }

    /**
     * Destroy instance.
     */

  }, {
    key: 'destroy',
    value: function destroy() {
      this.clearLocalHooks();
      this.close();
      this.parentMenu = null;
      this.eventManager.destroy();
    }

    /**
     * Checks if menu was opened.
     *
     * @returns {Boolean} Returns `true` if menu was opened.
     */

  }, {
    key: 'isOpened',
    value: function isOpened() {
      return this.hotMenu !== null;
    }

    /**
     * Execute menu command.
     *
     * @param {Event} [event]
     */

  }, {
    key: 'executeCommand',
    value: function executeCommand(event) {
      if (!this.isOpened() || !this.hotMenu.getSelected()) {
        return;
      }
      var selectedItem = this.hotMenu.getSourceDataAtRow(this.hotMenu.getSelected()[0]);

      this.runLocalHooks('select', selectedItem, event);

      if (selectedItem.isCommand === false || selectedItem.name === _predefinedItems.SEPARATOR) {
        return;
      }
      var selRange = this.hot.getSelectedRange();
      var normalizedSelection = selRange ? (0, _utils.normalizeSelection)(selRange) : {};
      var autoClose = true;

      // Don't close context menu if item is disabled or it has submenu
      if (selectedItem.disabled === true || typeof selectedItem.disabled === 'function' && selectedItem.disabled.call(this.hot) === true || selectedItem.submenu) {
        autoClose = false;
      }

      this.runLocalHooks('executeCommand', selectedItem.key, normalizedSelection, event);

      if (this.isSubMenu()) {
        this.parentMenu.runLocalHooks('executeCommand', selectedItem.key, normalizedSelection, event);
      }

      if (autoClose) {
        this.close(true);
      }
    }

    /**
     * Set menu position based on dom event or based on literal object.
     *
     * @param {Event|Object} coords Event or literal Object with coordinates.
     */

  }, {
    key: 'setPosition',
    value: function setPosition(coords) {
      var cursor = new _cursor2.default(coords);

      if (this.options.keepInViewport) {
        if (cursor.fitsBelow(this.container)) {
          this.setPositionBelowCursor(cursor);
        } else if (cursor.fitsAbove(this.container)) {
          this.setPositionAboveCursor(cursor);
        } else {
          this.setPositionBelowCursor(cursor);
        }
        if (cursor.fitsOnRight(this.container)) {
          this.setPositionOnRightOfCursor(cursor);
        } else {
          this.setPositionOnLeftOfCursor(cursor);
        }
      } else {
        this.setPositionBelowCursor(cursor);
        this.setPositionOnRightOfCursor(cursor);
      }
    }

    /**
     * Set menu position above cursor object.
     *
     * @param {Cursor} cursor `Cursor` object.
     */

  }, {
    key: 'setPositionAboveCursor',
    value: function setPositionAboveCursor(cursor) {
      var top = this.offset.above + cursor.top - this.container.offsetHeight;

      if (this.isSubMenu()) {
        top = cursor.top + cursor.cellHeight - this.container.offsetHeight + 3;
      }
      this.container.style.top = top + 'px';
    }

    /**
     * Set menu position below cursor object.
     *
     * @param {Cursor} cursor `Cursor` object.
     */

  }, {
    key: 'setPositionBelowCursor',
    value: function setPositionBelowCursor(cursor) {
      var top = this.offset.below + cursor.top;

      if (this.isSubMenu()) {
        top = cursor.top - 1;
      }
      this.container.style.top = top + 'px';
    }

    /**
     * Set menu position on the right of cursor object.
     *
     * @param {Cursor} cursor `Cursor` object.
     */

  }, {
    key: 'setPositionOnRightOfCursor',
    value: function setPositionOnRightOfCursor(cursor) {
      var left = void 0;

      if (this.isSubMenu()) {
        left = 1 + cursor.left + cursor.cellWidth;
      } else {
        left = this.offset.right + 1 + cursor.left;
      }

      this.container.style.left = left + 'px';
    }

    /**
     * Set menu position on the left of cursor object.
     *
     * @param {Cursor} cursor `Cursor` object.
     */

  }, {
    key: 'setPositionOnLeftOfCursor',
    value: function setPositionOnLeftOfCursor(cursor) {
      var left = this.offset.left + cursor.left - this.container.offsetWidth + (0, _element.getScrollbarWidth)() + 4;

      this.container.style.left = left + 'px';
    }

    /**
     * Select first cell in opened menu.
     */

  }, {
    key: 'selectFirstCell',
    value: function selectFirstCell() {
      var cell = this.hotMenu.getCell(0, 0);

      if ((0, _utils.isSeparator)(cell) || (0, _utils.isDisabled)(cell) || (0, _utils.isSelectionDisabled)(cell)) {
        this.selectNextCell(0, 0);
      } else {
        this.hotMenu.selectCell(0, 0);
      }
    }

    /**
     * Select last cell in opened menu.
     */

  }, {
    key: 'selectLastCell',
    value: function selectLastCell() {
      var lastRow = this.hotMenu.countRows() - 1;
      var cell = this.hotMenu.getCell(lastRow, 0);

      if ((0, _utils.isSeparator)(cell) || (0, _utils.isDisabled)(cell) || (0, _utils.isSelectionDisabled)(cell)) {
        this.selectPrevCell(lastRow, 0);
      } else {
        this.hotMenu.selectCell(lastRow, 0);
      }
    }

    /**
     * Select next cell in opened menu.
     *
     * @param {Number} row Row index.
     * @param {Number} col Column index.
     */

  }, {
    key: 'selectNextCell',
    value: function selectNextCell(row, col) {
      var nextRow = row + 1;
      var cell = nextRow < this.hotMenu.countRows() ? this.hotMenu.getCell(nextRow, col) : null;

      if (!cell) {
        return;
      }
      if ((0, _utils.isSeparator)(cell) || (0, _utils.isDisabled)(cell) || (0, _utils.isSelectionDisabled)(cell)) {
        this.selectNextCell(nextRow, col);
      } else {
        this.hotMenu.selectCell(nextRow, col);
      }
    }

    /**
     * Select previous cell in opened menu.
     *
     * @param {Number} row Row index.
     * @param {Number} col Column index.
     */

  }, {
    key: 'selectPrevCell',
    value: function selectPrevCell(row, col) {
      var prevRow = row - 1;
      var cell = prevRow >= 0 ? this.hotMenu.getCell(prevRow, col) : null;

      if (!cell) {
        return;
      }
      if ((0, _utils.isSeparator)(cell) || (0, _utils.isDisabled)(cell) || (0, _utils.isSelectionDisabled)(cell)) {
        this.selectPrevCell(prevRow, col);
      } else {
        this.hotMenu.selectCell(prevRow, col);
      }
    }

    /**
     * Menu item renderer.
     *
     * @private
     */

  }, {
    key: 'menuItemRenderer',
    value: function menuItemRenderer(hot, TD, row, col, prop, value) {
      var _this4 = this;

      var item = hot.getSourceDataAtRow(row);
      var wrapper = document.createElement('div');

      var isSubMenu = function isSubMenu(item) {
        return (0, _object.hasOwnProperty)(item, 'submenu');
      };
      var itemIsSeparator = function itemIsSeparator(item) {
        return new RegExp(_predefinedItems.SEPARATOR, 'i').test(item.name);
      };
      var itemIsDisabled = function itemIsDisabled(item) {
        return item.disabled === true || typeof item.disabled == 'function' && item.disabled.call(_this4.hot) === true;
      };
      var itemIsSelectionDisabled = function itemIsSelectionDisabled(item) {
        return item.disableSelection;
      };

      if (typeof value === 'function') {
        value = value.call(this.hot);
      }
      (0, _element.empty)(TD);
      (0, _element.addClass)(wrapper, 'htItemWrapper');
      (0, _element.addClass)(wrapper, item.key); // COSMOCODE
      TD.appendChild(wrapper);

      if (itemIsSeparator(item)) {
        (0, _element.addClass)(TD, 'htSeparator');
      } else if (typeof item.renderer === 'function') {
        (0, _element.addClass)(TD, 'htCustomMenuRenderer');
        TD.appendChild(item.renderer(hot, wrapper, row, col, prop, value));
      } else {
        (0, _element.fastInnerHTML)(wrapper, value);
      }
      if (itemIsDisabled(item)) {
        (0, _element.addClass)(TD, 'htDisabled');
        this.eventManager.addEventListener(TD, 'mouseenter', function () {
          return hot.deselectCell();
        });
      } else if (itemIsSelectionDisabled(item)) {
        (0, _element.addClass)(TD, 'htSelectionDisabled');
        this.eventManager.addEventListener(TD, 'mouseenter', function () {
          return hot.deselectCell();
        });
      } else if (isSubMenu(item)) {
        (0, _element.addClass)(TD, 'htSubmenu');

        if (itemIsSelectionDisabled(item)) {
          this.eventManager.addEventListener(TD, 'mouseenter', function () {
            return hot.deselectCell();
          });
        } else {
          this.eventManager.addEventListener(TD, 'mouseenter', function () {
            return hot.selectCell(row, col, void 0, void 0, false, false);
          });
        }
      } else {
        (0, _element.removeClass)(TD, 'htSubmenu');
        (0, _element.removeClass)(TD, 'htDisabled');

        if (itemIsSelectionDisabled(item)) {
          this.eventManager.addEventListener(TD, 'mouseenter', function () {
            return hot.deselectCell();
          });
        } else {
          this.eventManager.addEventListener(TD, 'mouseenter', function () {
            return hot.selectCell(row, col, void 0, void 0, false, false);
          });
        }
      }
    }

    /**
     * Create container/wrapper for handsontable.
     *
     * @private
     * @param {String} [name] Class name.
     * @returns {HTMLElement}
     */

  }, {
    key: 'createContainer',
    value: function createContainer() {
      var name = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;

      if (name) {
        name = name.replace(/[^A-z0-9]/g, '_');
        name = this.options.className + 'Sub_' + name;
      }
      var container = void 0;

      if (name) {
        container = document.querySelector('.' + this.options.className + '.' + name);
      } else {
        container = document.querySelector('.' + this.options.className);
      }
      if (!container) {
        container = document.createElement('div');
        (0, _element.addClass)(container, 'htMenu ' + this.options.className);

        if (name) {
          (0, _element.addClass)(container, name);
        }
        document.getElementsByTagName('body')[0].appendChild(container);
      }

      return container;
    }

    /**
     * @private
     */

  }, {
    key: 'blockMainTableCallbacks',
    value: function blockMainTableCallbacks() {
      this._afterScrollCallback = function () {};
      this.hot.addHook('afterScrollVertically', this._afterScrollCallback);
      this.hot.addHook('afterScrollHorizontally', this._afterScrollCallback);
    }

    /**
     * @private
     */

  }, {
    key: 'releaseMainTableCallbacks',
    value: function releaseMainTableCallbacks() {
      if (this._afterScrollCallback) {
        this.hot.removeHook('afterScrollVertically', this._afterScrollCallback);
        this.hot.removeHook('afterScrollHorizontally', this._afterScrollCallback);
        this._afterScrollCallback = null;
      }
    }

    /**
     * On before key down listener.
     *
     * @private
     * @param {Event} event
     */

  }, {
    key: 'onBeforeKeyDown',
    value: function onBeforeKeyDown(event) {
      var selection = this.hotMenu.getSelected();
      var stopEvent = false;
      this.keyEvent = true;

      switch (event.keyCode) {
        case _unicode.KEY_CODES.ESCAPE:
          this.close();
          stopEvent = true;
          break;

        case _unicode.KEY_CODES.ENTER:
          if (selection) {
            if (this.hotMenu.getSourceDataAtRow(selection[0]).submenu) {
              stopEvent = true;
            } else {
              this.executeCommand(event);
              this.close(true);
            }
          }
          break;

        case _unicode.KEY_CODES.ARROW_DOWN:
          if (selection) {
            this.selectNextCell(selection[0], selection[1]);
          } else {
            this.selectFirstCell();
          }
          stopEvent = true;
          break;

        case _unicode.KEY_CODES.ARROW_UP:
          if (selection) {
            this.selectPrevCell(selection[0], selection[1]);
          } else {
            this.selectLastCell();
          }
          stopEvent = true;
          break;

        case _unicode.KEY_CODES.ARROW_RIGHT:
          if (selection) {
            var menu = this.openSubMenu(selection[0]);

            if (menu) {
              menu.selectFirstCell();
            }
          }
          stopEvent = true;

          break;

        case _unicode.KEY_CODES.ARROW_LEFT:
          if (selection && this.isSubMenu()) {
            this.close();

            if (this.parentMenu) {
              this.parentMenu.hotMenu.listen();
            }
            stopEvent = true;
          }
          break;
        default:
          break;
      }
      if (stopEvent) {
        event.preventDefault();
        (0, _event.stopImmediatePropagation)(event);
      }

      this.keyEvent = false;
    }

    /**
     * On after init listener.
     *
     * @private
     */

  }, {
    key: 'onAfterInit',
    value: function onAfterInit() {
      var data = this.hotMenu.getSettings().data;
      var hiderStyle = this.hotMenu.view.wt.wtTable.hider.style;
      var holderStyle = this.hotMenu.view.wt.wtTable.holder.style;
      var currentHiderWidth = parseInt(hiderStyle.width, 10);

      var realHeight = (0, _array.arrayReduce)(data, function (accumulator, value) {
        return accumulator + (value.name === _predefinedItems.SEPARATOR ? 1 : 26);
      }, 0);

      holderStyle.width = currentHiderWidth + 22 + 'px';
      holderStyle.height = realHeight + 4 + 'px';
      hiderStyle.height = holderStyle.height;
    }

    /**
     * On after selection listener.
     *
     * @param {Number} r Selection start row index.
     * @param {Number} c Selection start column index.
     * @param {Number} r2 Selection end row index.
     * @param {Number} c2 Selection end column index.
     * @param {Object} preventScrolling Object with `value` property where its value change will be observed.
     */

  }, {
    key: 'onAfterSelection',
    value: function onAfterSelection(r, c, r2, c2, preventScrolling) {
      if (this.keyEvent === false) {
        preventScrolling.value = true;
      }
    }

    /**
     * Document mouse down listener.
     *
     * @private
     * @param {Event} event
     */

  }, {
    key: 'onDocumentMouseDown',
    value: function onDocumentMouseDown(event) {
      if (!this.isOpened()) {
        return;
      }
      if (this.container && (0, _element.isChildOf)(event.target, this.container)) {
        this.executeCommand(event);
      }
      // Close menu when clicked element is not belongs to menu itself
      if (this.options.standalone && this.hotMenu && !(0, _element.isChildOf)(event.target, this.hotMenu.rootElement)) {
        this.close(true);

        // Automatically close menu when clicked element is not belongs to menu or submenu (not necessarily to itself)
      } else if ((this.isAllSubMenusClosed() || this.isSubMenu()) && !(0, _element.isChildOf)(event.target, '.htMenu') && (0, _element.isChildOf)(event.target, document)) {
        this.close(true);
      }
    }
  }]);

  return Menu;
}();

(0, _object.mixin)(Menu, _localHooks2.default);

exports.default = Menu;

/***/ }),
/* 344 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


exports.__esModule = true;
exports.KEY = undefined;
exports.default = alignmentItem;

var _utils = __webpack_require__(19);

var _separator = __webpack_require__(73);

var KEY = exports.KEY = 'alignment';

function alignmentItem() {
  return {
    key: KEY,
    name: 'Alignment',
    disabled: function disabled() {
      return !(this.getSelectedRange() && !this.selection.selectedHeader.corner);
    },

    submenu: {
      items: [{
        key: KEY + ':left',
        name: function name() {
          var _this = this;

          var label = 'Left';
          var hasClass = (0, _utils.checkSelectionConsistency)(this.getSelectedRange(), function (row, col) {
            var className = _this.getCellMeta(row, col).className;

            if (className && className.indexOf('htLeft') !== -1) {
              return true;
            }
          });

          if (hasClass) {
            label = (0, _utils.markLabelAsSelected)(label);
          }

          return label;
        },
        callback: function callback() {
          var _this2 = this;

          var range = this.getSelectedRange();
          var stateBefore = (0, _utils.getAlignmentClasses)(range, function (row, col) {
            return _this2.getCellMeta(row, col).className;
          });
          var type = 'horizontal';
          var alignment = 'htLeft';

          this.runHooks('beforeCellAlignment', stateBefore, range, type, alignment);
          (0, _utils.align)(range, type, alignment, function (row, col) {
            return _this2.getCellMeta(row, col);
          }, function (row, col, key, value) {
            return _this2.setCellMeta(row, col, key, value);
          });
          this.render();
        },

        disabled: false
      }, {
        key: KEY + ':center',
        name: function name() {
          var _this3 = this;

          var label = 'Center';
          var hasClass = (0, _utils.checkSelectionConsistency)(this.getSelectedRange(), function (row, col) {
            var className = _this3.getCellMeta(row, col).className;

            if (className && className.indexOf('htCenter') !== -1) {
              return true;
            }
          });

          if (hasClass) {
            label = (0, _utils.markLabelAsSelected)(label);
          }

          return label;
        },
        callback: function callback() {
          var _this4 = this;

          var range = this.getSelectedRange();
          var stateBefore = (0, _utils.getAlignmentClasses)(range, function (row, col) {
            return _this4.getCellMeta(row, col).className;
          });
          var type = 'horizontal';
          var alignment = 'htCenter';

          this.runHooks('beforeCellAlignment', stateBefore, range, type, alignment);
          (0, _utils.align)(range, type, alignment, function (row, col) {
            return _this4.getCellMeta(row, col);
          }, function (row, col, key, value) {
            return _this4.setCellMeta(row, col, key, value);
          });
          this.render();
        },

        disabled: false
      }, {
        key: KEY + ':right',
        name: function name() {
          var _this5 = this;

          var label = 'Right';
          var hasClass = (0, _utils.checkSelectionConsistency)(this.getSelectedRange(), function (row, col) {
            var className = _this5.getCellMeta(row, col).className;

            if (className && className.indexOf('htRight') !== -1) {
              return true;
            }
          });

          if (hasClass) {
            label = (0, _utils.markLabelAsSelected)(label);
          }

          return label;
        },
        callback: function callback() {
          var _this6 = this;

          var range = this.getSelectedRange();
          var stateBefore = (0, _utils.getAlignmentClasses)(range, function (row, col) {
            return _this6.getCellMeta(row, col).className;
          });
          var type = 'horizontal';
          var alignment = 'htRight';

          this.runHooks('beforeCellAlignment', stateBefore, range, type, alignment);
          (0, _utils.align)(range, type, alignment, function (row, col) {
            return _this6.getCellMeta(row, col);
          }, function (row, col, key, value) {
            return _this6.setCellMeta(row, col, key, value);
          });
          this.render();
        },

        disabled: false
      }, {
        key: KEY + ':justify',
        name: function name() {
          var _this7 = this;

          var label = 'Justify';
          var hasClass = (0, _utils.checkSelectionConsistency)(this.getSelectedRange(), function (row, col) {
            var className = _this7.getCellMeta(row, col).className;

            if (className && className.indexOf('htJustify') !== -1) {
              return true;
            }
          });

          if (hasClass) {
            label = (0, _utils.markLabelAsSelected)(label);
          }

          return label;
        },
        callback: function callback() {
          var _this8 = this;

          var range = this.getSelectedRange();
          var stateBefore = (0, _utils.getAlignmentClasses)(range, function (row, col) {
            return _this8.getCellMeta(row, col).className;
          });
          var type = 'horizontal';
          var alignment = 'htJustify';

          this.runHooks('beforeCellAlignment', stateBefore, range, type, alignment);
          (0, _utils.align)(range, type, alignment, function (row, col) {
            return _this8.getCellMeta(row, col);
          }, function (row, col, key, value) {
            return _this8.setCellMeta(row, col, key, value);
          });
          this.render();
        },

        disabled: false
      }, {
        name: _separator.KEY
      }, {
        key: KEY + ':top',
        name: function name() {
          var _this9 = this;

          var label = 'Top';
          var hasClass = (0, _utils.checkSelectionConsistency)(this.getSelectedRange(), function (row, col) {
            var className = _this9.getCellMeta(row, col).className;

            if (className && className.indexOf('htTop') !== -1) {
              return true;
            }
          });

          if (hasClass) {
            label = (0, _utils.markLabelAsSelected)(label);
          }
          return label;
        },
        callback: function callback() {
          var _this10 = this;

          var range = this.getSelectedRange();
          var stateBefore = (0, _utils.getAlignmentClasses)(range, function (row, col) {
            return _this10.getCellMeta(row, col).className;
          });
          var type = 'vertical';
          var alignment = 'htTop';

          this.runHooks('beforeCellAlignment', stateBefore, range, type, alignment);
          (0, _utils.align)(range, type, alignment, function (row, col) {
            return _this10.getCellMeta(row, col);
          }, function (row, col, key, value) {
            return _this10.setCellMeta(row, col, key, value);
          });
          this.render();
        },

        disabled: false
      }, {
        key: KEY + ':middle',
        name: function name() {
          var _this11 = this;

          var label = 'Middle';
          var hasClass = (0, _utils.checkSelectionConsistency)(this.getSelectedRange(), function (row, col) {
            var className = _this11.getCellMeta(row, col).className;

            if (className && className.indexOf('htMiddle') !== -1) {
              return true;
            }
          });

          if (hasClass) {
            label = (0, _utils.markLabelAsSelected)(label);
          }

          return label;
        },
        callback: function callback() {
          var _this12 = this;

          var range = this.getSelectedRange();
          var stateBefore = (0, _utils.getAlignmentClasses)(range, function (row, col) {
            return _this12.getCellMeta(row, col).className;
          });
          var type = 'vertical';
          var alignment = 'htMiddle';

          this.runHooks('beforeCellAlignment', stateBefore, range, type, alignment);
          (0, _utils.align)(range, type, alignment, function (row, col) {
            return _this12.getCellMeta(row, col);
          }, function (row, col, key, value) {
            return _this12.setCellMeta(row, col, key, value);
          });
          this.render();
        },

        disabled: false
      }, {
        key: KEY + ':bottom',
        name: function name() {
          var _this13 = this;

          var label = 'Bottom';
          var hasClass = (0, _utils.checkSelectionConsistency)(this.getSelectedRange(), function (row, col) {
            var className = _this13.getCellMeta(row, col).className;

            if (className && className.indexOf('htBottom') !== -1) {
              return true;
            }
          });

          if (hasClass) {
            label = (0, _utils.markLabelAsSelected)(label);
          }

          return label;
        },
        callback: function callback() {
          var _this14 = this;

          var range = this.getSelectedRange();
          var stateBefore = (0, _utils.getAlignmentClasses)(range, function (row, col) {
            return _this14.getCellMeta(row, col).className;
          });
          var type = 'vertical';
          var alignment = 'htBottom';

          this.runHooks('beforeCellAlignment', stateBefore, range, type, alignment);
          (0, _utils.align)(range, type, alignment, function (row, col) {
            return _this14.getCellMeta(row, col);
          }, function (row, col, key, value) {
            return _this14.setCellMeta(row, col, key, value);
          });
          this.render();
        },

        disabled: false
      }]
    }
  };
}

/***/ }),
/* 345 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


exports.__esModule = true;
exports.KEY = undefined;
exports.default = clearColumnItem;

var _utils = __webpack_require__(19);

var KEY = exports.KEY = 'clear_column';

function clearColumnItem() {
  return {
    key: KEY,
    name: 'Clear column',

    callback: function callback(key, selection) {
      var column = selection.start.col;

      if (this.countRows()) {
        this.populateFromArray(0, column, [[null]], Math.max(selection.start.row, selection.end.row), column, 'ContextMenu.clearColumn');
      }
    },
    disabled: function disabled() {
      var selected = (0, _utils.getValidSelection)(this);

      if (!selected) {
        return true;
      }
      var entireRowSelection = [selected[0], 0, selected[0], this.countCols() - 1];
      var rowSelected = entireRowSelection.join(',') == selected.join(',');

      return selected[1] < 0 || this.countCols() >= this.getSettings().maxCols || rowSelected;
    }
  };
}

/***/ }),
/* 346 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


exports.__esModule = true;
exports.KEY = undefined;
exports.default = columnLeftItem;

var _utils = __webpack_require__(19);

var KEY = exports.KEY = 'col_left';

function columnLeftItem() {
  return {
    key: KEY,
    name: 'Insert column on the left',
    callback: function callback(key, selection) {
      this.alter('insert_col', selection.start.col, 1, 'ContextMenu.columnLeft');
    },
    disabled: function disabled() {
      var selected = (0, _utils.getValidSelection)(this);

      if (!selected) {
        return true;
      }
      if (!this.isColumnModificationAllowed()) {
        return true;
      }
      var entireRowSelection = [selected[0], 0, selected[0], this.countCols() - 1];
      var rowSelected = entireRowSelection.join(',') == selected.join(',');
      var onlyOneColumn = this.countCols() === 1;

      return selected[1] < 0 || this.countCols() >= this.getSettings().maxCols || !onlyOneColumn && rowSelected;
    },
    hidden: function hidden() {
      return !this.getSettings().allowInsertColumn;
    }
  };
}

/***/ }),
/* 347 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


exports.__esModule = true;
exports.KEY = undefined;
exports.default = columnRightItem;

var _utils = __webpack_require__(19);

var KEY = exports.KEY = 'col_right';

function columnRightItem() {
  return {
    key: KEY,
    name: 'Insert column on the right',

    callback: function callback(key, selection) {
      this.alter('insert_col', selection.end.col + 1, 1, 'ContextMenu.columnRight');
    },
    disabled: function disabled() {
      var selected = (0, _utils.getValidSelection)(this);

      if (!selected) {
        return true;
      }
      if (!this.isColumnModificationAllowed()) {
        return true;
      }
      var entireRowSelection = [selected[0], 0, selected[0], this.countCols() - 1];
      var rowSelected = entireRowSelection.join(',') == selected.join(',');
      var onlyOneColumn = this.countCols() === 1;

      return selected[1] < 0 || this.countCols() >= this.getSettings().maxCols || !onlyOneColumn && rowSelected;
    },
    hidden: function hidden() {
      return !this.getSettings().allowInsertColumn;
    }
  };
}

/***/ }),
/* 348 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


exports.__esModule = true;
exports.KEY = undefined;
exports.default = readOnlyItem;

var _utils = __webpack_require__(19);

var KEY = exports.KEY = 'make_read_only';

function readOnlyItem() {
  return {
    key: KEY,
    name: function name() {
      var _this = this;

      var label = 'Read only';
      var atLeastOneReadOnly = (0, _utils.checkSelectionConsistency)(this.getSelectedRange(), function (row, col) {
        return _this.getCellMeta(row, col).readOnly;
      });

      if (atLeastOneReadOnly) {
        label = (0, _utils.markLabelAsSelected)(label);
      }

      return label;
    },
    callback: function callback() {
      var _this2 = this;

      var range = this.getSelectedRange();
      var atLeastOneReadOnly = (0, _utils.checkSelectionConsistency)(range, function (row, col) {
        return _this2.getCellMeta(row, col).readOnly;
      });

      range.forAll(function (row, col) {
        _this2.setCellMeta(row, col, 'readOnly', !atLeastOneReadOnly);
      });
      this.render();
    },
    disabled: function disabled() {
      return !(this.getSelectedRange() && !this.selection.selectedHeader.corner);
    }
  };
}

/***/ }),
/* 349 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


exports.__esModule = true;
exports.default = redoItem;
var KEY = exports.KEY = 'redo';

function redoItem() {
  return {
    key: KEY,
    name: 'Redo',

    callback: function callback() {
      this.redo();
    },
    disabled: function disabled() {
      return this.undoRedo && !this.undoRedo.isRedoAvailable();
    }
  };
}

/***/ }),
/* 350 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


exports.__esModule = true;
exports.KEY = undefined;
exports.default = removeColumnItem;

var _utils = __webpack_require__(19);

var KEY = exports.KEY = 'remove_col';

function removeColumnItem() {
  return {
    key: KEY,
    name: 'Remove column',

    callback: function callback(key, selection) {
      var amount = selection.end.col - selection.start.col + 1;

      this.alter('remove_col', selection.start.col, amount, 'ContextMenu.removeColumn');
    },
    disabled: function disabled() {
      var selected = (0, _utils.getValidSelection)(this);
      var totalColumns = this.countCols();

      return !selected || this.selection.selectedHeader.rows || this.selection.selectedHeader.corner || !this.isColumnModificationAllowed() || !totalColumns;
    },
    hidden: function hidden() {
      return !this.getSettings().allowRemoveColumn;
    }
  };
}

/***/ }),
/* 351 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


exports.__esModule = true;
exports.KEY = undefined;
exports.default = removeRowItem;

var _utils = __webpack_require__(19);

var KEY = exports.KEY = 'remove_row';

function removeRowItem() {
  return {
    key: KEY,
    name: 'Remove row',

    callback: function callback(key, selection) {
      var amount = selection.end.row - selection.start.row + 1;

      this.alter('remove_row', selection.start.row, amount, 'ContextMenu.removeRow');
    },
    disabled: function disabled() {
      var selected = (0, _utils.getValidSelection)(this);
      var totalRows = this.countRows();

      return !selected || this.selection.selectedHeader.cols || this.selection.selectedHeader.corner || !totalRows;
    },
    hidden: function hidden() {
      return !this.getSettings().allowRemoveRow;
    }
  };
}

/***/ }),
/* 352 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


exports.__esModule = true;
exports.KEY = undefined;
exports.default = rowAboveItem;

var _utils = __webpack_require__(19);

var KEY = exports.KEY = 'row_above';

function rowAboveItem() {
  return {
    key: KEY,
    name: 'Insert row above',

    callback: function callback(key, selection) {
      this.alter('insert_row', selection.start.row, 1, 'ContextMenu.rowAbove');
    },
    disabled: function disabled() {
      var selected = (0, _utils.getValidSelection)(this);

      return !selected || this.selection.selectedHeader.cols || this.countRows() >= this.getSettings().maxRows;
    },
    hidden: function hidden() {
      return !this.getSettings().allowInsertRow;
    }
  };
}

/***/ }),
/* 353 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


exports.__esModule = true;
exports.KEY = undefined;
exports.default = rowBelowItem;

var _utils = __webpack_require__(19);

var KEY = exports.KEY = 'row_below';

function rowBelowItem() {
  return {
    key: KEY,
    name: 'Insert row below',

    callback: function callback(key, selection) {
      this.alter('insert_row', selection.end.row + 1, 1, 'ContextMenu.rowBelow');
    },
    disabled: function disabled() {
      var selected = (0, _utils.getValidSelection)(this);

      return !selected || this.selection.selectedHeader.cols || this.countRows() >= this.getSettings().maxRows;
    },
    hidden: function hidden() {
      return !this.getSettings().allowInsertRow;
    }
  };
}

/***/ }),
/* 354 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


exports.__esModule = true;
exports.default = undoItem;
var KEY = exports.KEY = 'undo';

function undoItem() {
  return {
    key: KEY,
    name: 'Undo',

    callback: function callback() {
      this.undo();
    },
    disabled: function disabled() {
      return this.undoRedo && !this.undoRedo.isUndoAvailable();
    }
  };
}

/***/ }),
/* 355 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


exports.__esModule = true;
exports.default = copyItem;
function copyItem(copyPastePlugin) {
  return {
    key: 'copy',
    name: 'Copy',
    callback: function callback() {
      copyPastePlugin.setCopyableText();
      copyPastePlugin.copy(true);
    },
    disabled: function disabled() {
      return !copyPastePlugin.hot.getSelected();
    },

    hidden: false
  };
}

/***/ }),
/* 356 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


exports.__esModule = true;
exports.default = cutItem;
function cutItem(copyPastePlugin) {
  return {
    key: 'cut',
    name: 'Cut',
    callback: function callback() {
      copyPastePlugin.setCopyableText();
      copyPastePlugin.cut(true);
    },
    disabled: function disabled() {
      return !copyPastePlugin.hot.getSelected();
    },

    hidden: false
  };
}

/***/ }),
/* 357 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


exports.__esModule = true;

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

var _createClass = 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); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

var _get = function get(object, property, receiver) { if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ("value" in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } };

var _base = __webpack_require__(16);

var _base2 = _interopRequireDefault(_base);

var _pluginHooks = __webpack_require__(11);

var _pluginHooks2 = _interopRequireDefault(_pluginHooks);

var _SheetClip = __webpack_require__(249);

var _SheetClip2 = _interopRequireDefault(_SheetClip);

var _src = __webpack_require__(14);

var _unicode = __webpack_require__(15);

var _element = __webpack_require__(0);

var _array = __webpack_require__(2);

var _number = __webpack_require__(5);

var _event = __webpack_require__(7);

var _plugins = __webpack_require__(9);

var _textarea = __webpack_require__(358);

var _textarea2 = _interopRequireDefault(_textarea);

var _copy = __webpack_require__(355);

var _copy2 = _interopRequireDefault(_copy);

var _cut = __webpack_require__(356);

var _cut2 = _interopRequireDefault(_cut);

var _eventManager = __webpack_require__(4);

var _eventManager2 = _interopRequireDefault(_eventManager);

__webpack_require__(300);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }

function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }

_pluginHooks2.default.getSingleton().register('afterCopyLimit');
_pluginHooks2.default.getSingleton().register('modifyCopyableRange');
_pluginHooks2.default.getSingleton().register('beforeCut');
_pluginHooks2.default.getSingleton().register('afterCut');
_pluginHooks2.default.getSingleton().register('beforePaste');
_pluginHooks2.default.getSingleton().register('afterPaste');
_pluginHooks2.default.getSingleton().register('beforeCopy');
_pluginHooks2.default.getSingleton().register('afterCopy');

var ROWS_LIMIT = 1000;
var COLUMNS_LIMIT = 1000;
var privatePool = new WeakMap();

/**
 * @description
 * This plugin enables the copy/paste functionality in the Handsontable.
 *
 * @example
 * ```js
 * ...
 * copyPaste: true,
 * ...
 * ```
 * @class CopyPaste
 * @plugin CopyPaste
 */

var CopyPaste = function (_BasePlugin) {
  _inherits(CopyPaste, _BasePlugin);

  function CopyPaste(hotInstance) {
    _classCallCheck(this, CopyPaste);

    /**
     * Event manager
     *
     * @type {EventManager}
     */
    var _this = _possibleConstructorReturn(this, (CopyPaste.__proto__ || Object.getPrototypeOf(CopyPaste)).call(this, hotInstance));

    _this.eventManager = new _eventManager2.default(_this);
    /**
     * Maximum number of columns than can be copied to clipboard using <kbd>CTRL</kbd> + <kbd>C</kbd>.
     *
     * @private
     * @type {Number}
     * @default 1000
     */
    _this.columnsLimit = COLUMNS_LIMIT;
    /**
     * Ranges of the cells coordinates, which should be used to copy/cut/paste actions.
     *
     * @private
     * @type {Array}
     */
    _this.copyableRanges = [];
    /**
     * Defines paste (<kbd>CTRL</kbd> + <kbd>V</kbd>) behavior.
     * * Default value `"overwrite"` will paste clipboard value over current selection.
     * * When set to `"shift_down"`, clipboard data will be pasted in place of current selection, while all selected cells are moved down.
     * * When set to `"shift_right"`, clipboard data will be pasted in place of current selection, while all selected cells are moved right.
     *
     * @private
     * @type {String}
     * @default 'overwrite'
     */
    _this.pasteMode = 'overwrite';
    /**
     * Maximum number of rows than can be copied to clipboard using <kbd>CTRL</kbd> + <kbd>C</kbd>.
     *
     * @private
     * @type {Number}
     * @default 1000
     */
    _this.rowsLimit = ROWS_LIMIT;
    /**
     * The `textarea` element which is necessary to process copying, cutting off and pasting.
     *
     * @private
     * @type {HTMLElement}
     * @default undefined
     */
    _this.textarea = void 0;

    privatePool.set(_this, {
      isTriggeredByPaste: false
    });
    return _this;
  }

  /**
   * Check if plugin is enabled.
   *
   * @returns {Boolean}
   */


  _createClass(CopyPaste, [{
    key: 'isEnabled',
    value: function isEnabled() {
      return !!this.hot.getSettings().copyPaste;
    }

    /**
     * Enable the plugin.
     */

  }, {
    key: 'enablePlugin',
    value: function enablePlugin() {
      var _this2 = this;

      if (this.enabled) {
        return;
      }

      var settings = this.hot.getSettings();

      this.textarea = _textarea2.default.getSingleton();

      if (_typeof(settings.copyPaste) === 'object') {
        this.pasteMode = settings.copyPaste.pasteMode || this.pasteMode;
        this.rowsLimit = settings.copyPaste.rowsLimit || this.rowsLimit;
        this.columnsLimit = settings.copyPaste.columnsLimit || this.columnsLimit;
      }

      this.addHook('afterContextMenuDefaultOptions', function (options) {
        return _this2.onAfterContextMenuDefaultOptions(options);
      });
      this.addHook('beforeKeyDown', function (event) {
        return _this2.onBeforeKeyDown(event);
      });

      this.registerEvents();

      _get(CopyPaste.prototype.__proto__ || Object.getPrototypeOf(CopyPaste.prototype), 'enablePlugin', this).call(this);
    }
    /**
     * Updates the plugin to use the latest options you have specified.
     */

  }, {
    key: 'updatePlugin',
    value: function updatePlugin() {
      this.disablePlugin();
      this.enablePlugin();

      _get(CopyPaste.prototype.__proto__ || Object.getPrototypeOf(CopyPaste.prototype), 'updatePlugin', this).call(this);
    }

    /**
     * Disable plugin for this Handsontable instance.
     */

  }, {
    key: 'disablePlugin',
    value: function disablePlugin() {
      if (this.textarea) {
        this.textarea.destroy();
      }

      _get(CopyPaste.prototype.__proto__ || Object.getPrototypeOf(CopyPaste.prototype), 'disablePlugin', this).call(this);
    }

    /**
     * Prepares copyable text from the cells selection in the invisible textarea.
     *
     * @function setCopyable
     * @memberof CopyPaste#
     */

  }, {
    key: 'setCopyableText',
    value: function setCopyableText() {
      var selRange = this.hot.getSelectedRange();

      if (!selRange) {
        return;
      }

      var topLeft = selRange.getTopLeftCorner();
      var bottomRight = selRange.getBottomRightCorner();
      var startRow = topLeft.row;
      var startCol = topLeft.col;
      var endRow = bottomRight.row;
      var endCol = bottomRight.col;
      var finalEndRow = Math.min(endRow, startRow + this.rowsLimit - 1);
      var finalEndCol = Math.min(endCol, startCol + this.columnsLimit - 1);

      this.copyableRanges.length = 0;

      this.copyableRanges.push({
        startRow: startRow,
        startCol: startCol,
        endRow: finalEndRow,
        endCol: finalEndCol
      });

      this.copyableRanges = this.hot.runHooks('modifyCopyableRange', this.copyableRanges);

      var copyableData = this.getRangedCopyableData(this.copyableRanges);

      this.textarea.setValue(copyableData);

      if (endRow !== finalEndRow || endCol !== finalEndCol) {
        this.hot.runHooks('afterCopyLimit', endRow - startRow + 1, endCol - startCol + 1, this.rowsLimit, this.columnsLimit);
      }
    }

    /**
     * Create copyable text releated to range objects.
     *
     * @since 0.19.0
     * @param {Array} ranges Array of Objects with properties `startRow`, `endRow`, `startCol` and `endCol`.
     * @returns {String} Returns string which will be copied into clipboard.
     */

  }, {
    key: 'getRangedCopyableData',
    value: function getRangedCopyableData(ranges) {
      var _this3 = this;

      var dataSet = [];
      var copyableRows = [];
      var copyableColumns = [];

      // Count all copyable rows and columns
      (0, _array.arrayEach)(ranges, function (range) {
        (0, _number.rangeEach)(range.startRow, range.endRow, function (row) {
          if (copyableRows.indexOf(row) === -1) {
            copyableRows.push(row);
          }
        });
        (0, _number.rangeEach)(range.startCol, range.endCol, function (column) {
          if (copyableColumns.indexOf(column) === -1) {
            copyableColumns.push(column);
          }
        });
      });
      // Concat all rows and columns data defined in ranges into one copyable string
      (0, _array.arrayEach)(copyableRows, function (row) {
        var rowSet = [];

        (0, _array.arrayEach)(copyableColumns, function (column) {
          rowSet.push(_this3.hot.getCopyableData(row, column));
        });

        dataSet.push(rowSet);
      });

      return _SheetClip2.default.stringify(dataSet);
    }

    /**
     * Create copyable text releated to range objects.
     *
     * @since 0.31.1
     * @param {Array} ranges Array of Objects with properties `startRow`, `startCol`, `endRow` and `endCol`.
     * @returns {Array} Returns array of arrays which will be copied into clipboard.
     */

  }, {
    key: 'getRangedData',
    value: function getRangedData(ranges) {
      var _this4 = this;

      var dataSet = [];
      var copyableRows = [];
      var copyableColumns = [];

      // Count all copyable rows and columns
      (0, _array.arrayEach)(ranges, function (range) {
        (0, _number.rangeEach)(range.startRow, range.endRow, function (row) {
          if (copyableRows.indexOf(row) === -1) {
            copyableRows.push(row);
          }
        });
        (0, _number.rangeEach)(range.startCol, range.endCol, function (column) {
          if (copyableColumns.indexOf(column) === -1) {
            copyableColumns.push(column);
          }
        });
      });
      // Concat all rows and columns data defined in ranges into one copyable string
      (0, _array.arrayEach)(copyableRows, function (row) {
        var rowSet = [];

        (0, _array.arrayEach)(copyableColumns, function (column) {
          rowSet.push(_this4.hot.getCopyableData(row, column));
        });

        dataSet.push(rowSet);
      });

      return dataSet;
    }

    /**
     * Copy action.
     *
     * @param {Boolean} isTriggeredByClick Flag to determine that copy action was executed by the mouse click.
     */

  }, {
    key: 'copy',
    value: function copy(isTriggeredByClick) {
      var rangedData = this.getRangedData(this.copyableRanges);

      var allowCopying = !!this.hot.runHooks('beforeCopy', rangedData, this.copyableRanges);

      if (allowCopying) {
        this.textarea.setValue(_SheetClip2.default.stringify(rangedData));
        this.textarea.select();

        if (isTriggeredByClick) {
          document.execCommand('copy');
        }

        this.hot.runHooks('afterCopy', rangedData, this.copyableRanges);
      } else {
        this.textarea.setValue('');
      }
    }

    /**
     * Cut action.
     *
     * @param {Boolean} isTriggeredByClick Flag to determine that cut action was executed by the mouse click.
     */

  }, {
    key: 'cut',
    value: function cut(isTriggeredByClick) {
      var rangedData = this.getRangedData(this.copyableRanges);

      var allowCuttingOut = !!this.hot.runHooks('beforeCut', rangedData, this.copyableRanges);

      if (allowCuttingOut) {
        this.textarea.setValue(_SheetClip2.default.stringify(rangedData));
        this.hot.selection.empty();
        this.textarea.select();

        if (isTriggeredByClick) {
          document.execCommand('cut');
        }

        this.hot.runHooks('afterCut', rangedData, this.copyableRanges);
      } else {
        this.textarea.setValue('');
      }
    }

    /**
     * Simulated paste action.
     *
     * @param {String} [value=''] New value, which should be `pasted`.
     */

  }, {
    key: 'paste',
    value: function paste() {
      var value = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '';

      this.textarea.setValue(value);

      this.onPaste();
      this.onInput();
    }

    /**
     * Register event listeners.
     *
     * @private
     */

  }, {
    key: 'registerEvents',
    value: function registerEvents() {
      var _this5 = this;

      this.eventManager.addEventListener(this.textarea.element, 'paste', function (event) {
        return _this5.onPaste(event);
      });
      this.eventManager.addEventListener(this.textarea.element, 'input', function (event) {
        return _this5.onInput(event);
      });
    }

    /**
     * Trigger to make possible observe `onInput` in textarea.
     *
     * @private
     */

  }, {
    key: 'triggerPaste',
    value: function triggerPaste() {
      this.textarea.select();

      this.onPaste();
    }

    /**
     * `paste` event callback on textarea element.
     *
     * @private
     */

  }, {
    key: 'onPaste',
    value: function onPaste() {
      var priv = privatePool.get(this);

      priv.isTriggeredByPaste = true;
    }

    /**
     * `input` event callback is called after `paste` event callback.
     *
     * @private
     */

  }, {
    key: 'onInput',
    value: function onInput() {
      var _this6 = this;

      var priv = privatePool.get(this);

      if (!this.hot.isListening() || !priv.isTriggeredByPaste) {
        return;
      }

      priv.isTriggeredByPaste = false;

      var input = void 0,
          inputArray = void 0,
          selected = void 0,
          coordsFrom = void 0,
          coordsTo = void 0,
          cellRange = void 0,
          topLeftCorner = void 0,
          bottomRightCorner = void 0,
          areaStart = void 0,
          areaEnd = void 0;

      input = this.textarea.getValue();
      inputArray = _SheetClip2.default.parse(input);

      var allowPasting = !!this.hot.runHooks('beforePaste', inputArray, this.copyableRanges);

      if (!allowPasting) {
        return;
      }

      selected = this.hot.getSelected();
      coordsFrom = new _src.CellCoords(selected[0], selected[1]);
      coordsTo = new _src.CellCoords(selected[2], selected[3]);
      cellRange = new _src.CellRange(coordsFrom, coordsFrom, coordsTo);
      topLeftCorner = cellRange.getTopLeftCorner();
      bottomRightCorner = cellRange.getBottomRightCorner();
      areaStart = topLeftCorner;
      areaEnd = new _src.CellCoords(Math.max(bottomRightCorner.row, inputArray.length - 1 + topLeftCorner.row), Math.max(bottomRightCorner.col, inputArray[0].length - 1 + topLeftCorner.col));

      var isSelRowAreaCoverInputValue = coordsTo.row - coordsFrom.row >= inputArray.length - 1;
      var isSelColAreaCoverInputValue = coordsTo.col - coordsFrom.col >= inputArray[0].length - 1;

      this.hot.addHookOnce('afterChange', function (changes, source) {
        var changesLength = changes ? changes.length : 0;

        if (changesLength) {
          var offset = { row: 0, col: 0 };
          var highestColumnIndex = -1;

          (0, _array.arrayEach)(changes, function (change, index) {
            var nextChange = changesLength > index + 1 ? changes[index + 1] : null;

            if (nextChange) {
              if (!isSelRowAreaCoverInputValue) {
                offset.row += Math.max(nextChange[0] - change[0] - 1, 0);
              }
              if (!isSelColAreaCoverInputValue && change[1] > highestColumnIndex) {
                highestColumnIndex = change[1];
                offset.col += Math.max(nextChange[1] - change[1] - 1, 0);
              }
            }
          });
          _this6.hot.selectCell(areaStart.row, areaStart.col, areaEnd.row + offset.row, areaEnd.col + offset.col);
        }
      });

      this.hot.populateFromArray(areaStart.row, areaStart.col, inputArray, areaEnd.row, areaEnd.col, 'CopyPaste.paste', this.pasteMode);
      this.hot.runHooks('afterPaste', inputArray, this.copyableRanges);
    }

    /**
     * Add copy, cut and paste options to the Context Menu.
     *
     * @private
     * @param {Object} options Contains default added options of the Context Menu.
     */

  }, {
    key: 'onAfterContextMenuDefaultOptions',
    value: function onAfterContextMenuDefaultOptions(options) {
      options.items.push({
        name: '---------'
      }, (0, _copy2.default)(this), (0, _cut2.default)(this));
    }

    /**
     * beforeKeyDown callback.
     *
     * @private
     * @param {Event} event
     */

  }, {
    key: 'onBeforeKeyDown',
    value: function onBeforeKeyDown(event) {
      var _this7 = this;

      if (!this.hot.getSelected()) {
        return;
      }
      if (this.hot.getActiveEditor() && this.hot.getActiveEditor().isOpened()) {
        return;
      }
      if ((0, _event.isImmediatePropagationStopped)(event)) {
        return;
      }
      if (!this.textarea.isActive() && (0, _element.getSelectionText)()) {
        return;
      }

      if ((0, _unicode.isCtrlKey)(event.keyCode)) {
        // When fragmentSelection is enabled and some text is selected then don't blur selection calling 'setCopyableText'
        if (this.hot.getSettings().fragmentSelection && (0, _element.getSelectionText)()) {
          return;
        }

        // when CTRL is pressed, prepare selectable text in textarea
        this.setCopyableText();
        (0, _event.stopImmediatePropagation)(event);

        return;
      }

      // catch CTRL but not right ALT (which in some systems triggers ALT+CTRL)
      var ctrlDown = (event.ctrlKey || event.metaKey) && !event.altKey;

      if (ctrlDown) {
        if (event.keyCode == _unicode.KEY_CODES.A) {
          setTimeout(function () {
            _this7.setCopyableText();
          }, 0);
        }
        if (event.keyCode == _unicode.KEY_CODES.X) {
          this.cut();
        }
        if (event.keyCode == _unicode.KEY_CODES.C) {
          this.copy();
        }
        if (event.keyCode == _unicode.KEY_CODES.V) {
          this.triggerPaste();
        }
      }
    }

    /**
     * Destroy plugin instance.
     */

  }, {
    key: 'destroy',
    value: function destroy() {
      if (this.textarea) {
        this.textarea.destroy();
      }

      _get(CopyPaste.prototype.__proto__ || Object.getPrototypeOf(CopyPaste.prototype), 'destroy', this).call(this);
    }
  }]);

  return CopyPaste;
}(_base2.default);

(0, _plugins.registerPlugin)('CopyPaste', CopyPaste);

exports.default = CopyPaste;

/***/ }),
/* 358 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


exports.__esModule = true;

var _createClass = 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); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

/**
 * @class Textarea
 *
 * @plugin CopyPaste
 */
var Textarea = function () {
  _createClass(Textarea, null, [{
    key: 'getSingleton',
    value: function getSingleton() {
      globalSingleton.append();

      return globalSingleton;
    }
  }]);

  function Textarea() {
    _classCallCheck(this, Textarea);

    /**
     * Main textarea element.
     *
     * @type {HTMLElement}
     */
    this.element = void 0;
    /**
     * Store information about append to the document.body.
     *
     * @type {Boolean}
     */
    this.isAppended = false;
    /**
     * Reference counter.
     *
     * @type {Number}
     */
    this.refCounter = 0;
  }

  /**
   * Apends textarea element to the `body`
   */


  _createClass(Textarea, [{
    key: 'append',
    value: function append() {
      if (this.hasBeenDestroyed()) {
        this.create();
      }

      this.refCounter++;

      if (!this.isAppended && document.body) {
        if (document.body) {
          this.isAppended = true;
          document.body.appendChild(this.element);
        }
      }
    }

    /**
     * Prepares textarea element with proper attributes.
     */

  }, {
    key: 'create',
    value: function create() {
      this.element = document.createElement('textarea');
      this.element.id = 'HandsontableCopyPaste';
      this.element.className = 'copyPaste';
      this.element.tabIndex = -1;
      this.element.autocomplete = 'off';
      this.element.wrap = 'off';
    }

    /**
     * Deselects textarea element if is active.
     */

  }, {
    key: 'deselect',
    value: function deselect() {
      if (this.element === document.activeElement) {
        document.activeElement.blur();
      }
    }

    /**
     * Destroy instance
     */

  }, {
    key: 'destroy',
    value: function destroy() {
      this.refCounter--;
      this.refCounter = this.refCounter < 0 ? 0 : this.refCounter;

      if (this.hasBeenDestroyed() && this.element && this.element.parentNode) {
        this.element.parentNode.removeChild(this.element);
        this.element = null;
        this.isAppended = false;
      }
    }

    /**
     * Getter for the element.
     *
     * @returns {String}
     */

  }, {
    key: 'getValue',
    value: function getValue() {
      return this.element.value;
    }

    /**
     * Check if instance has been destroyed
     *
     * @returns {Boolean}
     */

  }, {
    key: 'hasBeenDestroyed',
    value: function hasBeenDestroyed() {
      return this.refCounter < 1;
    }

    /**
     * Check if the element is an active element in frame.
     *
     * @returns {Boolean}
     */

  }, {
    key: 'isActive',
    value: function isActive() {
      return this.element === document.activeElement;
    }

    /**
     * Sets focus on the element and select content.
     */

  }, {
    key: 'select',
    value: function select() {
      this.element.focus();
      this.element.select();
    }

    /**
     * Setter for the element.
     *
     * @param {String} data Value which should be insert into the element.
     */

  }, {
    key: 'setValue',
    value: function setValue(data) {
      this.element.value = data;
    }
  }]);

  return Textarea;
}();

var globalSingleton = new Textarea();

exports.default = Textarea;

/***/ }),
/* 359 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


exports.__esModule = true;

var _pluginHooks = __webpack_require__(11);

var _pluginHooks2 = _interopRequireDefault(_pluginHooks);

var _eventManager = __webpack_require__(4);

var _eventManager2 = _interopRequireDefault(_eventManager);

var _plugins = __webpack_require__(9);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

/**
 * @description
 * Plugin used to scroll Handsontable by selecting a cell and dragging outside of the visible viewport.
 *
 * @private
 * @class DragToScroll
 * @plugin DragToScroll
 */
function DragToScroll() {
  this.boundaries = null;
  this.callback = null;
}

/**
 * @param boundaries {Object} compatible with getBoundingClientRect
 */
DragToScroll.prototype.setBoundaries = function (boundaries) {
  this.boundaries = boundaries;
};

/**
 * @param callback {Function}
 */
DragToScroll.prototype.setCallback = function (callback) {
  this.callback = callback;
};

/**
 * Check if mouse position (x, y) is outside of the viewport
 * @param x
 * @param y
 */
DragToScroll.prototype.check = function (x, y) {
  var diffX = 0;
  var diffY = 0;

  if (y < this.boundaries.top) {
    // y is less than top
    diffY = y - this.boundaries.top;
  } else if (y > this.boundaries.bottom) {
    // y is more than bottom
    diffY = y - this.boundaries.bottom;
  }

  if (x < this.boundaries.left) {
    // x is less than left
    diffX = x - this.boundaries.left;
  } else if (x > this.boundaries.right) {
    // x is more than right
    diffX = x - this.boundaries.right;
  }

  this.callback(diffX, diffY);
};

var dragToScroll;
var instance;

var setupListening = function setupListening(instance) {
  instance.dragToScrollListening = false;
  var scrollHandler = instance.view.wt.wtTable.holder; // native scroll
  dragToScroll = new DragToScroll();

  if (scrollHandler === window) {
    // not much we can do currently
    return;
  }

  dragToScroll.setBoundaries(scrollHandler.getBoundingClientRect());
  dragToScroll.setCallback(function (scrollX, scrollY) {
    if (scrollX < 0) {
      scrollHandler.scrollLeft -= 50;
    } else if (scrollX > 0) {
      scrollHandler.scrollLeft += 50;
    }

    if (scrollY < 0) {
      scrollHandler.scrollTop -= 20;
    } else if (scrollY > 0) {
      scrollHandler.scrollTop += 20;
    }
  });

  instance.dragToScrollListening = true;
};

_pluginHooks2.default.getSingleton().add('afterInit', function () {
  var instance = this;
  var eventManager = new _eventManager2.default(this);

  eventManager.addEventListener(document, 'mouseup', function () {
    instance.dragToScrollListening = false;
  });

  eventManager.addEventListener(document, 'mousemove', function (event) {
    if (instance.dragToScrollListening) {
      dragToScroll.check(event.clientX, event.clientY);
    }
  });
});

_pluginHooks2.default.getSingleton().add('afterDestroy', function () {
  new _eventManager2.default(this).clear();
});

_pluginHooks2.default.getSingleton().add('afterOnCellMouseDown', function () {
  setupListening(this);
});

_pluginHooks2.default.getSingleton().add('afterOnCellCornerMouseDown', function () {
  setupListening(this);
});

exports.default = DragToScroll;

/***/ }),
/* 360 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


exports.__esModule = true;
exports.default = freezeColumnItem;
function freezeColumnItem(manualColumnFreezePlugin) {
  return {
    key: 'freeze_column',
    name: 'Freeze this column',
    callback: function callback() {
      var selectedColumn = this.getSelectedRange().from.col;

      manualColumnFreezePlugin.freezeColumn(selectedColumn);

      this.render();
      this.view.wt.wtOverlays.adjustElementsSize(true);
    },
    hidden: function hidden() {
      var selection = this.getSelectedRange();
      var hide = false;

      if (selection === void 0) {
        hide = true;
      } else if (selection.from.col !== selection.to.col || selection.from.col <= this.getSettings().fixedColumnsLeft - 1) {
        hide = true;
      }

      return hide;
    }
  };
}

/***/ }),
/* 361 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


exports.__esModule = true;
exports.default = unfreezeColumnItem;
function unfreezeColumnItem(manualColumnFreezePlugin) {
  return {
    key: 'unfreeze_column',
    name: 'Unfreeze this column',
    callback: function callback() {
      var selectedColumn = this.getSelectedRange().from.col;

      manualColumnFreezePlugin.unfreezeColumn(selectedColumn);

      this.render();
      this.view.wt.wtOverlays.adjustElementsSize(true);
    },
    hidden: function hidden() {
      var selection = this.getSelectedRange();
      var hide = false;

      if (selection === void 0) {
        hide = true;
      } else if (selection.from.col !== selection.to.col || selection.from.col >= this.getSettings().fixedColumnsLeft) {
        hide = true;
      }

      return hide;
    }
  };
}

/***/ }),
/* 362 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


exports.__esModule = true;

var _createClass = 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); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

var _get = function get(object, property, receiver) { if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ("value" in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } };

var _base = __webpack_require__(16);

var _base2 = _interopRequireDefault(_base);

var _plugins = __webpack_require__(9);

var _array = __webpack_require__(2);

var _freezeColumn = __webpack_require__(360);

var _freezeColumn2 = _interopRequireDefault(_freezeColumn);

var _unfreezeColumn = __webpack_require__(361);

var _unfreezeColumn2 = _interopRequireDefault(_unfreezeColumn);

__webpack_require__(301);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }

function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }

var privatePool = new WeakMap();
/**
 * This plugin allows to manually "freeze" and "unfreeze" a column using an entry in the Context Menu.
 * You can turn it on by setting a `manualColumnFreeze` property to `true`.
 *
 * @plugin ManualColumnFreeze
 * @dependencies ManualColumnMove
 */

var ManualColumnFreeze = function (_BasePlugin) {
  _inherits(ManualColumnFreeze, _BasePlugin);

  function ManualColumnFreeze(hotInstance) {
    _classCallCheck(this, ManualColumnFreeze);

    var _this = _possibleConstructorReturn(this, (ManualColumnFreeze.__proto__ || Object.getPrototypeOf(ManualColumnFreeze)).call(this, hotInstance));

    privatePool.set(_this, {
      moveByFreeze: false,
      afterFirstUse: false
    });
    /**
     * Original column positions
     *
     * @type {Array}
     */
    _this.frozenColumnsBasePositions = [];
    /**
     * Reference to the `ManualColumnMove` plugin.
     */
    _this.manualColumnMovePlugin = void 0;
    return _this;
  }

  /**
   * Check if the plugin is enabled in the Handsontable settings.
   *
   * @returns {Boolean}
   */


  _createClass(ManualColumnFreeze, [{
    key: 'isEnabled',
    value: function isEnabled() {
      return !!this.hot.getSettings().manualColumnFreeze;
    }

    /**
     * Enable plugin for this Handsontable instance.
     */

  }, {
    key: 'enablePlugin',
    value: function enablePlugin() {
      var _this2 = this;

      if (this.enabled) {
        return;
      }

      this.addHook('afterContextMenuDefaultOptions', function (options) {
        return _this2.addContextMenuEntry(options);
      });
      this.addHook('afterInit', function () {
        return _this2.onAfterInit();
      });
      this.addHook('beforeColumnMove', function (rows, target) {
        return _this2.onBeforeColumnMove(rows, target);
      });

      _get(ManualColumnFreeze.prototype.__proto__ || Object.getPrototypeOf(ManualColumnFreeze.prototype), 'enablePlugin', this).call(this);
    }

    /**
     * Disable plugin for this Handsontable instance.
     */

  }, {
    key: 'disablePlugin',
    value: function disablePlugin() {
      var priv = privatePool.get(this);

      priv.afterFirstUse = false;
      priv.moveByFreeze = false;

      _get(ManualColumnFreeze.prototype.__proto__ || Object.getPrototypeOf(ManualColumnFreeze.prototype), 'disablePlugin', this).call(this);
    }

    /**
     * Updates the plugin to use the latest options you have specified.
     */

  }, {
    key: 'updatePlugin',
    value: function updatePlugin() {
      this.disablePlugin();
      this.enablePlugin();

      _get(ManualColumnFreeze.prototype.__proto__ || Object.getPrototypeOf(ManualColumnFreeze.prototype), 'updatePlugin', this).call(this);
    }

    /**
     * Freeze the given column (add it to fixed columns).
     *
     * @param {Number} column Visual column index.
     */

  }, {
    key: 'freezeColumn',
    value: function freezeColumn(column) {
      var priv = privatePool.get(this);
      var settings = this.hot.getSettings();

      if (!priv.afterFirstUse) {
        priv.afterFirstUse = true;
      }

      if (settings.fixedColumnsLeft === this.hot.countCols() || column <= settings.fixedColumnsLeft - 1) {
        return; // already fixed
      }

      priv.moveByFreeze = true;

      if (column !== this.getMovePlugin().columnsMapper.getValueByIndex(column)) {
        this.frozenColumnsBasePositions[settings.fixedColumnsLeft] = column;
      }

      this.getMovePlugin().moveColumn(column, settings.fixedColumnsLeft++);
    }

    /**
     * Unfreeze the given column (remove it from fixed columns and bring to it's previous position).
     *
     * @param {Number} column Visual column index.
     */

  }, {
    key: 'unfreezeColumn',
    value: function unfreezeColumn(column) {
      var priv = privatePool.get(this);
      var settings = this.hot.getSettings();

      if (!priv.afterFirstUse) {
        priv.afterFirstUse = true;
      }

      if (settings.fixedColumnsLeft <= 0 || column > settings.fixedColumnsLeft - 1) {
        return; // not fixed
      }

      var returnCol = this.getBestColumnReturnPosition(column);

      priv.moveByFreeze = true;
      settings.fixedColumnsLeft--;

      this.getMovePlugin().moveColumn(column, returnCol + 1);
    }

    /**
     * Get the reference to the ManualColumnMove plugin.
     *
     * @private
     * @returns {Object}
     */

  }, {
    key: 'getMovePlugin',
    value: function getMovePlugin() {
      if (!this.manualColumnMovePlugin) {
        this.manualColumnMovePlugin = this.hot.getPlugin('manualColumnMove');
      }

      return this.manualColumnMovePlugin;
    }

    /**
     * Estimates the most fitting return position for unfrozen column.
     *
     * @private
     * @param {Number} column Visual column index.
     */

  }, {
    key: 'getBestColumnReturnPosition',
    value: function getBestColumnReturnPosition(column) {
      var movePlugin = this.getMovePlugin();
      var settings = this.hot.getSettings();
      var i = settings.fixedColumnsLeft;
      var j = movePlugin.columnsMapper.getValueByIndex(i);
      var initialCol = void 0;

      if (this.frozenColumnsBasePositions[column] == null) {
        initialCol = movePlugin.columnsMapper.getValueByIndex(column);

        while (j < initialCol) {
          i++;
          j = movePlugin.columnsMapper.getValueByIndex(i);
        }
      } else {
        initialCol = this.frozenColumnsBasePositions[column];
        this.frozenColumnsBasePositions[column] = void 0;

        while (j <= initialCol) {
          i++;
          j = movePlugin.columnsMapper.getValueByIndex(i);
        }
        i = j;
      }

      return i - 1;
    }
    /**
     * Add the manualColumnFreeze context menu entries.
     *
     * @private
     * @param {Object} options Context menu options.
     */

  }, {
    key: 'addContextMenuEntry',
    value: function addContextMenuEntry(options) {
      options.items.push({ name: '---------' }, (0, _freezeColumn2.default)(this), (0, _unfreezeColumn2.default)(this));
    }

    /**
     * Enabling `manualColumnMove` plugin on `afterInit` hook.
     *
     * @private
     */

  }, {
    key: 'onAfterInit',
    value: function onAfterInit() {
      if (!this.getMovePlugin().isEnabled()) {
        this.getMovePlugin().enablePlugin();
      }
    }

    /**
     * Prevent moving the rows from/to fixed area.
     *
     * @private
     * @param {Array} rows
     * @param {Number} target
     */

  }, {
    key: 'onBeforeColumnMove',
    value: function onBeforeColumnMove(rows, target) {
      var priv = privatePool.get(this);

      if (priv.afterFirstUse && !priv.moveByFreeze) {
        var frozenLen = this.hot.getSettings().fixedColumnsLeft;
        var disallowMoving = target < frozenLen;

        if (!disallowMoving) {
          (0, _array.arrayEach)(rows, function (value, index, array) {
            if (value < frozenLen) {
              disallowMoving = true;
              return false;
            }
          });
        }

        if (disallowMoving) {
          return false;
        }
      }

      if (priv.moveByFreeze) {
        priv.moveByFreeze = false;
      }
    }

    /**
     * Destroy plugin instance.
     */

  }, {
    key: 'destroy',
    value: function destroy() {
      _get(ManualColumnFreeze.prototype.__proto__ || Object.getPrototypeOf(ManualColumnFreeze.prototype), 'destroy', this).call(this);
    }
  }]);

  return ManualColumnFreeze;
}(_base2.default);

(0, _plugins.registerPlugin)('manualColumnFreeze', ManualColumnFreeze);

exports.default = ManualColumnFreeze;

/***/ }),
/* 363 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


exports.__esModule = true;

var _createClass = 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); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

var _arrayMapper = __webpack_require__(265);

var _arrayMapper2 = _interopRequireDefault(_arrayMapper);

var _array = __webpack_require__(2);

var _object = __webpack_require__(3);

var _number = __webpack_require__(5);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

/**
 * @class ColumnsMapper
 * @plugin ManualColumnMove
 */
var ColumnsMapper = function () {
  function ColumnsMapper(manualColumnMove) {
    _classCallCheck(this, ColumnsMapper);

    /**
     * Instance of ManualColumnMove plugin.
     *
     * @type {ManualColumnMove}
     */
    this.manualColumnMove = manualColumnMove;
  }

  /**
   * Reset current map array and create new one.
   *
   * @param {Number} [length] Custom generated map length.
   */


  _createClass(ColumnsMapper, [{
    key: 'createMap',
    value: function createMap(length) {
      var _this = this;

      var originLength = length === void 0 ? this._arrayMap.length : length;

      this._arrayMap.length = 0;

      (0, _number.rangeEach)(originLength - 1, function (itemIndex) {
        _this._arrayMap[itemIndex] = itemIndex;
      });
    }

    /**
     * Destroy class.
     */

  }, {
    key: 'destroy',
    value: function destroy() {
      this._arrayMap = null;
    }

    /**
     * Moving elements in columnsMapper.
     *
     * @param {Number} from Column index to move.
     * @param {Number} to Target index.
     */

  }, {
    key: 'moveColumn',
    value: function moveColumn(from, to) {
      var indexToMove = this._arrayMap[from];
      this._arrayMap[from] = null;
      this._arrayMap.splice(to, 0, indexToMove);
    }

    /**
     * Clearing arrayMap from `null` entries.
     */

  }, {
    key: 'clearNull',
    value: function clearNull() {
      this._arrayMap = (0, _array.arrayFilter)(this._arrayMap, function (i) {
        return i !== null;
      });
    }
  }]);

  return ColumnsMapper;
}();

(0, _object.mixin)(ColumnsMapper, _arrayMapper2.default);

exports.default = ColumnsMapper;

/***/ }),
/* 364 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


exports.__esModule = true;

var _createClass = 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); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

var _get = function get(object, property, receiver) { if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ("value" in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } };

var _base = __webpack_require__(16);

var _base2 = _interopRequireDefault(_base);

var _pluginHooks = __webpack_require__(11);

var _pluginHooks2 = _interopRequireDefault(_pluginHooks);

var _array = __webpack_require__(2);

var _element = __webpack_require__(0);

var _number = __webpack_require__(5);

var _eventManager = __webpack_require__(4);

var _eventManager2 = _interopRequireDefault(_eventManager);

var _plugins = __webpack_require__(9);

var _columnsMapper = __webpack_require__(363);

var _columnsMapper2 = _interopRequireDefault(_columnsMapper);

var _backlight = __webpack_require__(365);

var _backlight2 = _interopRequireDefault(_backlight);

var _guideline = __webpack_require__(366);

var _guideline2 = _interopRequireDefault(_guideline);

var _src = __webpack_require__(14);

__webpack_require__(302);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }

function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }

_pluginHooks2.default.getSingleton().register('beforeColumnMove');
_pluginHooks2.default.getSingleton().register('afterColumnMove');
_pluginHooks2.default.getSingleton().register('unmodifyCol');

var privatePool = new WeakMap();
var CSS_PLUGIN = 'ht__manualColumnMove';
var CSS_SHOW_UI = 'show-ui';
var CSS_ON_MOVING = 'on-moving--columns';
var CSS_AFTER_SELECTION = 'after-selection--columns';

/**
 * @plugin ManualColumnMove
 *
 * @description
 * This plugin allows to change columns order.
 *
 * API:
 * - moveColumn - move single column to the new position.
 * - moveColumns - move many columns (as an array of indexes) to the new position.
 *
 * If you want apply visual changes, you have to call manually the render() method on the instance of Handsontable.
 *
 * UI components:
 * - backlight - highlight of selected columns.
 * - guideline - line which shows where rows has been moved.
 *
 * @class ManualColumnMove
 * @plugin ManualColumnMove
 */

var ManualColumnMove = function (_BasePlugin) {
  _inherits(ManualColumnMove, _BasePlugin);

  function ManualColumnMove(hotInstance) {
    _classCallCheck(this, ManualColumnMove);

    /**
     * Set up WeakMap of plugin to sharing private parameters;
     */
    var _this = _possibleConstructorReturn(this, (ManualColumnMove.__proto__ || Object.getPrototypeOf(ManualColumnMove)).call(this, hotInstance));

    privatePool.set(_this, {
      columnsToMove: [],
      countCols: 0,
      fixedColumns: 0,
      pressed: void 0,
      disallowMoving: void 0,
      target: {
        eventPageX: void 0,
        coords: void 0,
        TD: void 0,
        col: void 0
      }
    });

    /**
     * List of last removed row indexes.
     *
     * @type {Array}
     */
    _this.removedColumns = [];
    /**
     * Object containing visual row indexes mapped to data source indexes.
     *
     * @type {RowsMapper}
     */
    _this.columnsMapper = new _columnsMapper2.default(_this);
    /**
     * Event Manager object.
     *
     * @type {Object}
     */
    _this.eventManager = new _eventManager2.default(_this);
    /**
     * Backlight UI object.
     *
     * @type {Object}
     */
    _this.backlight = new _backlight2.default(hotInstance);
    /**
     * Guideline UI object.
     *
     * @type {Object}
     */
    _this.guideline = new _guideline2.default(hotInstance);
    return _this;
  }

  /**
   * Check if plugin is enabled.
   *
   * @returns {Boolean}
   */


  _createClass(ManualColumnMove, [{
    key: 'isEnabled',
    value: function isEnabled() {
      return !!this.hot.getSettings().manualColumnMove;
    }

    /**
     * Enable the plugin.
     */

  }, {
    key: 'enablePlugin',
    value: function enablePlugin() {
      var _this2 = this;

      if (this.enabled) {
        return;
      }

      this.addHook('beforeOnCellMouseDown', function (event, coords, TD, blockCalculations) {
        return _this2.onBeforeOnCellMouseDown(event, coords, TD, blockCalculations);
      });
      this.addHook('beforeOnCellMouseOver', function (event, coords, TD, blockCalculations) {
        return _this2.onBeforeOnCellMouseOver(event, coords, TD, blockCalculations);
      });
      this.addHook('afterScrollVertically', function () {
        return _this2.onAfterScrollVertically();
      });
      this.addHook('modifyCol', function (row, source) {
        return _this2.onModifyCol(row, source);
      });
      this.addHook('beforeRemoveCol', function (index, amount) {
        return _this2.onBeforeRemoveCol(index, amount);
      });
      this.addHook('afterRemoveCol', function (index, amount) {
        return _this2.onAfterRemoveCol(index, amount);
      });
      this.addHook('afterCreateCol', function (index, amount) {
        return _this2.onAfterCreateCol(index, amount);
      });
      this.addHook('afterLoadData', function (firstTime) {
        return _this2.onAfterLoadData(firstTime);
      });
      this.addHook('unmodifyCol', function (column) {
        return _this2.onUnmodifyCol(column);
      });

      this.registerEvents();

      // TODO: move adding plugin classname to BasePlugin.
      (0, _element.addClass)(this.hot.rootElement, CSS_PLUGIN);

      _get(ManualColumnMove.prototype.__proto__ || Object.getPrototypeOf(ManualColumnMove.prototype), 'enablePlugin', this).call(this);
    }

    /**
     * Updates the plugin to use the latest options you have specified.
     */

  }, {
    key: 'updatePlugin',
    value: function updatePlugin() {
      this.disablePlugin();
      this.enablePlugin();

      this.onAfterPluginsInitialized();

      _get(ManualColumnMove.prototype.__proto__ || Object.getPrototypeOf(ManualColumnMove.prototype), 'updatePlugin', this).call(this);
    }

    /**
     * Disable plugin for this Handsontable instance.
     */

  }, {
    key: 'disablePlugin',
    value: function disablePlugin() {
      var pluginSettings = this.hot.getSettings().manualColumnMove;

      if (Array.isArray(pluginSettings)) {
        this.columnsMapper.clearMap();
      }

      (0, _element.removeClass)(this.hot.rootElement, CSS_PLUGIN);

      this.unregisterEvents();
      this.backlight.destroy();
      this.guideline.destroy();

      _get(ManualColumnMove.prototype.__proto__ || Object.getPrototypeOf(ManualColumnMove.prototype), 'disablePlugin', this).call(this);
    }

    /**
     * Move a single column.
     *
     * @param {Number} column Visual column index to be moved.
     * @param {Number} target Visual column index being a target for the moved column.
     */

  }, {
    key: 'moveColumn',
    value: function moveColumn(column, target) {
      this.moveColumns([column], target);
    }

    /**
     * Move multiple columns.
     *
     * @param {Array} columns Array of visual column indexes to be moved.
     * @param {Number} target Visual column index being a target for the moved columns.
     */

  }, {
    key: 'moveColumns',
    value: function moveColumns(columns, target) {
      var _this3 = this;

      var priv = privatePool.get(this);
      var beforeColumnHook = this.hot.runHooks('beforeColumnMove', columns, target);

      priv.disallowMoving = !beforeColumnHook;

      if (beforeColumnHook !== false) {
        // first we need to rewrite an visual indexes to physical for save reference after move
        (0, _array.arrayEach)(columns, function (column, index, array) {
          array[index] = _this3.columnsMapper.getValueByIndex(column);
        });

        // next, when we have got an physical indexes, we can move columns
        (0, _array.arrayEach)(columns, function (column, index) {
          var actualPosition = _this3.columnsMapper.getIndexByValue(column);

          if (actualPosition !== target) {
            _this3.columnsMapper.moveColumn(actualPosition, target + index);
          }
        });

        // after moving we have to clear columnsMapper from null entries
        this.columnsMapper.clearNull();
      }

      this.hot.runHooks('afterColumnMove', columns, target);
    }

    /**
     * Correct the cell selection after the move action. Fired only when action was made with a mouse.
     * That means that changing the column order using the API won't correct the selection.
     *
     * @private
     * @param {Number} startColumn Visual column index for the start of the selection.
     * @param {Number} endColumn Visual column index for the end of the selection.
     */

  }, {
    key: 'changeSelection',
    value: function changeSelection(startColumn, endColumn) {
      var selection = this.hot.selection;
      var lastRowIndex = this.hot.countRows() - 1;

      selection.setRangeStartOnly(new _src.CellCoords(0, startColumn));
      selection.setRangeEnd(new _src.CellCoords(lastRowIndex, endColumn), false);
    }

    /**
     * Get the sum of the widths of columns in the provided range.
     *
     * @private
     * @param {Number} from Visual column index.
     * @param {Number} to Visual column index.
     * @returns {Number}
     */

  }, {
    key: 'getColumnsWidth',
    value: function getColumnsWidth(from, to) {
      var width = 0;

      for (var i = from; i < to; i++) {
        var columnWidth = 0;

        if (i < 0) {
          columnWidth = this.hot.view.wt.wtTable.getColumnWidth(i) || 0;
        } else {
          columnWidth = this.hot.view.wt.wtTable.getStretchedColumnWidth(i) || 0;
        }

        width += columnWidth;
      }

      return width;
    }

    /**
     * Load initial settings when persistent state is saved or when plugin was initialized as an array.
     *
     * @private
     */

  }, {
    key: 'initialSettings',
    value: function initialSettings() {
      var pluginSettings = this.hot.getSettings().manualColumnMove;

      if (Array.isArray(pluginSettings)) {
        this.moveColumns(pluginSettings, 0);
      } else if (pluginSettings !== void 0) {
        this.persistentStateLoad();
      }
    }

    /**
     * Check if the provided column is in the fixedColumnsLeft section.
     *
     * @private
     * @param {Number} column Visual column index to check.
     * @returns {Boolean}
     */

  }, {
    key: 'isFixedColumnsLeft',
    value: function isFixedColumnsLeft(column) {
      return column < this.hot.getSettings().fixedColumnsLeft;
    }

    /**
     * Save the manual column positions to the persistent state.
     *
     * @private
     */

  }, {
    key: 'persistentStateSave',
    value: function persistentStateSave() {
      this.hot.runHooks('persistentStateSave', 'manualColumnMove', this.columnsMapper._arrayMap);
    }

    /**
     * Load the manual column positions from the persistent state.
     *
     * @private
     */

  }, {
    key: 'persistentStateLoad',
    value: function persistentStateLoad() {
      var storedState = {};

      this.hot.runHooks('persistentStateLoad', 'manualColumnMove', storedState);

      if (storedState.value) {
        this.columnsMapper._arrayMap = storedState.value;
      }
    }

    /**
     * Prepare array of indexes based on actual selection.
     *
     * @private
     * @returns {Array}
     */

  }, {
    key: 'prepareColumnsToMoving',
    value: function prepareColumnsToMoving(start, end) {
      var selectedColumns = [];

      (0, _number.rangeEach)(start, end, function (i) {
        selectedColumns.push(i);
      });

      return selectedColumns;
    }

    /**
     * Update the UI visual position.
     *
     * @private
     */

  }, {
    key: 'refreshPositions',
    value: function refreshPositions() {
      var priv = privatePool.get(this);
      var firstVisible = this.hot.view.wt.wtTable.getFirstVisibleColumn();
      var lastVisible = this.hot.view.wt.wtTable.getLastVisibleColumn();
      var wtTable = this.hot.view.wt.wtTable;
      var scrollableElement = this.hot.view.wt.wtOverlays.scrollableElement;
      var scrollLeft = typeof scrollableElement.scrollX === 'number' ? scrollableElement.scrollX : scrollableElement.scrollLeft;
      var tdOffsetLeft = this.hot.view.THEAD.offsetLeft + this.getColumnsWidth(0, priv.coordsColumn);
      var mouseOffsetLeft = priv.target.eventPageX - (priv.rootElementOffset - (scrollableElement.scrollX === void 0 ? scrollLeft : 0));
      var hiderWidth = wtTable.hider.offsetWidth;
      var tbodyOffsetLeft = wtTable.TBODY.offsetLeft;
      var backlightElemMarginLeft = this.backlight.getOffset().left;
      var backlightElemWidth = this.backlight.getSize().width;
      var rowHeaderWidth = 0;

      if (priv.rootElementOffset + wtTable.holder.offsetWidth + scrollLeft < priv.target.eventPageX) {
        if (priv.coordsColumn < priv.countCols) {
          priv.coordsColumn++;
        }
      }

      if (priv.hasRowHeaders) {
        rowHeaderWidth = this.hot.view.wt.wtOverlays.leftOverlay.clone.wtTable.getColumnHeader(-1).offsetWidth;
      }
      if (this.isFixedColumnsLeft(priv.coordsColumn)) {
        tdOffsetLeft += scrollLeft;
      }
      tdOffsetLeft += rowHeaderWidth;

      if (priv.coordsColumn < 0) {
        // if hover on rowHeader
        if (priv.fixedColumns > 0) {
          priv.target.col = 0;
        } else {
          priv.target.col = firstVisible > 0 ? firstVisible - 1 : firstVisible;
        }
      } else if (priv.target.TD.offsetWidth / 2 + tdOffsetLeft <= mouseOffsetLeft) {
        var newCoordsCol = priv.coordsColumn >= priv.countCols ? priv.countCols - 1 : priv.coordsColumn;
        // if hover on right part of TD
        priv.target.col = newCoordsCol + 1;
        // unfortunately first column is bigger than rest
        tdOffsetLeft += priv.target.TD.offsetWidth;

        if (priv.target.col > lastVisible) {
          this.hot.scrollViewportTo(void 0, lastVisible + 1, void 0, true);
        }
      } else {
        // elsewhere on table
        priv.target.col = priv.coordsColumn;

        if (priv.target.col <= firstVisible && priv.target.col >= priv.fixedColumns) {
          this.hot.scrollViewportTo(void 0, firstVisible - 1);
        }
      }

      if (priv.target.col <= firstVisible && priv.target.col >= priv.fixedColumns) {
        this.hot.scrollViewportTo(void 0, firstVisible - 1);
      }

      var backlightLeft = mouseOffsetLeft;
      var guidelineLeft = tdOffsetLeft;

      if (mouseOffsetLeft + backlightElemWidth + backlightElemMarginLeft >= hiderWidth) {
        // prevent display backlight on the right side of the table
        backlightLeft = hiderWidth - backlightElemWidth - backlightElemMarginLeft;
      } else if (mouseOffsetLeft + backlightElemMarginLeft < tbodyOffsetLeft + rowHeaderWidth) {
        // prevent display backlight on the left side of the table
        backlightLeft = tbodyOffsetLeft + rowHeaderWidth + Math.abs(backlightElemMarginLeft);
      }

      if (tdOffsetLeft >= hiderWidth - 1) {
        // prevent display guideline outside the table
        guidelineLeft = hiderWidth - 1;
      } else if (guidelineLeft === 0) {
        // guideline has got `margin-left: -1px` as default
        guidelineLeft = 1;
      } else if (scrollableElement.scrollX !== void 0 && priv.coordsColumn < priv.fixedColumns) {
        guidelineLeft -= priv.rootElementOffset <= scrollableElement.scrollX ? priv.rootElementOffset : 0;
      }

      this.backlight.setPosition(null, backlightLeft);
      this.guideline.setPosition(null, guidelineLeft);
    }

    /**
     * This method checks arrayMap from columnsMapper and updates the columnsMapper if it's necessary.
     *
     * @private
     */

  }, {
    key: 'updateColumnsMapper',
    value: function updateColumnsMapper() {
      var countCols = this.hot.countSourceCols();
      var columnsMapperLen = this.columnsMapper._arrayMap.length;

      if (columnsMapperLen === 0) {
        this.columnsMapper.createMap(countCols || this.hot.getSettings().startCols);
      } else if (columnsMapperLen < countCols) {
        var diff = countCols - columnsMapperLen;

        this.columnsMapper.insertItems(columnsMapperLen, diff);
      } else if (columnsMapperLen > countCols) {
        var maxIndex = countCols - 1;
        var columnsToRemove = [];

        (0, _array.arrayEach)(this.columnsMapper._arrayMap, function (value, index, array) {
          if (value > maxIndex) {
            columnsToRemove.push(index);
          }
        });

        this.columnsMapper.removeItems(columnsToRemove);
      }
    }

    /**
     * Bind the events used by the plugin.
     *
     * @private
     */

  }, {
    key: 'registerEvents',
    value: function registerEvents() {
      var _this4 = this;

      this.eventManager.addEventListener(document.documentElement, 'mousemove', function (event) {
        return _this4.onMouseMove(event);
      });
      this.eventManager.addEventListener(document.documentElement, 'mouseup', function () {
        return _this4.onMouseUp();
      });
    }

    /**
     * Unbind the events used by the plugin.
     *
     * @private
     */

  }, {
    key: 'unregisterEvents',
    value: function unregisterEvents() {
      this.eventManager.clear();
    }

    /**
     * Change the behavior of selection / dragging.
     *
     * @private
     * @param {MouseEvent} event `mousedown` event properties.
     * @param {CellCoords} coords Visual cell coordinates where was fired event.
     * @param {HTMLElement} TD Cell represented as HTMLElement.
     * @param {Object} blockCalculations Object which contains information about blockCalculation for row, column or cells.
     */

  }, {
    key: 'onBeforeOnCellMouseDown',
    value: function onBeforeOnCellMouseDown(event, coords, TD, blockCalculations) {
      var wtTable = this.hot.view.wt.wtTable;
      var isHeaderSelection = this.hot.selection.selectedHeader.cols;
      var selection = this.hot.getSelectedRange();
      var priv = privatePool.get(this);
      var isSortingElement = event.realTarget.className.indexOf('columnSorting') > -1;

      if (!selection || !isHeaderSelection || priv.pressed || event.button !== 0 || isSortingElement) {
        priv.pressed = false;
        priv.columnsToMove.length = 0;
        (0, _element.removeClass)(this.hot.rootElement, [CSS_ON_MOVING, CSS_SHOW_UI]);
        return;
      }

      var guidelineIsNotReady = this.guideline.isBuilt() && !this.guideline.isAppended();
      var backlightIsNotReady = this.backlight.isBuilt() && !this.backlight.isAppended();

      if (guidelineIsNotReady && backlightIsNotReady) {
        this.guideline.appendTo(wtTable.hider);
        this.backlight.appendTo(wtTable.hider);
      }

      var from = selection.from,
          to = selection.to;

      var start = Math.min(from.col, to.col);
      var end = Math.max(from.col, to.col);

      if (coords.row < 0 && coords.col >= start && coords.col <= end) {
        blockCalculations.column = true;
        priv.pressed = true;
        priv.target.eventPageX = event.pageX;
        priv.coordsColumn = coords.col;
        priv.target.TD = TD;
        priv.target.col = coords.col;
        priv.columnsToMove = this.prepareColumnsToMoving(start, end);
        priv.hasRowHeaders = !!this.hot.getSettings().rowHeaders;
        priv.countCols = this.hot.countCols();
        priv.fixedColumns = this.hot.getSettings().fixedColumnsLeft;
        priv.rootElementOffset = (0, _element.offset)(this.hot.rootElement).left;

        var countColumnsFrom = priv.hasRowHeaders ? -1 : 0;
        var topPos = wtTable.holder.scrollTop + wtTable.getColumnHeaderHeight(0) + 1;
        var fixedColumns = coords.col < priv.fixedColumns;
        var scrollableElement = this.hot.view.wt.wtOverlays.scrollableElement;
        var wrapperIsWindow = scrollableElement.scrollX ? scrollableElement.scrollX - priv.rootElementOffset : 0;

        var mouseOffset = event.layerX - (fixedColumns ? wrapperIsWindow : 0);
        var leftOffset = Math.abs(this.getColumnsWidth(start, coords.col) + mouseOffset);

        this.backlight.setPosition(topPos, this.getColumnsWidth(countColumnsFrom, start) + leftOffset);
        this.backlight.setSize(this.getColumnsWidth(start, end + 1), wtTable.hider.offsetHeight - topPos);
        this.backlight.setOffset(null, leftOffset * -1);

        (0, _element.addClass)(this.hot.rootElement, CSS_ON_MOVING);
      } else {
        (0, _element.removeClass)(this.hot.rootElement, CSS_AFTER_SELECTION);
        priv.pressed = false;
        priv.columnsToMove.length = 0;
      }
    }

    /**
     * 'mouseMove' event callback. Fired when pointer move on document.documentElement.
     *
     * @private
     * @param {MouseEvent} event `mousemove` event properties.
     */

  }, {
    key: 'onMouseMove',
    value: function onMouseMove(event) {
      var priv = privatePool.get(this);

      if (!priv.pressed) {
        return;
      }

      // callback for browser which doesn't supports CSS pointer-event: none
      if (event.realTarget === this.backlight.element) {
        var width = this.backlight.getSize().width;
        this.backlight.setSize(0);

        setTimeout(function () {
          this.backlight.setPosition(width);
        });
      }

      priv.target.eventPageX = event.pageX;
      this.refreshPositions();
    }

    /**
     * 'beforeOnCellMouseOver' hook callback. Fired when pointer was over cell.
     *
     * @private
     * @param {MouseEvent} event `mouseover` event properties.
     * @param {CellCoords} coords Visual cell coordinates where was fired event.
     * @param {HTMLElement} TD Cell represented as HTMLElement.
     * @param {Object} blockCalculations Object which contains information about blockCalculation for row, column or cells.
     */

  }, {
    key: 'onBeforeOnCellMouseOver',
    value: function onBeforeOnCellMouseOver(event, coords, TD, blockCalculations) {
      var selectedRange = this.hot.getSelectedRange();
      var priv = privatePool.get(this);

      if (!selectedRange || !priv.pressed) {
        return;
      }

      if (priv.columnsToMove.indexOf(coords.col) > -1) {
        (0, _element.removeClass)(this.hot.rootElement, CSS_SHOW_UI);
      } else {
        (0, _element.addClass)(this.hot.rootElement, CSS_SHOW_UI);
      }

      blockCalculations.row = true;
      blockCalculations.column = true;
      blockCalculations.cell = true;
      priv.coordsColumn = coords.col;
      priv.target.TD = TD;
    }

    /**
     * `onMouseUp` hook callback.
     *
     * @private
     */

  }, {
    key: 'onMouseUp',
    value: function onMouseUp() {
      var priv = privatePool.get(this);

      priv.coordsColumn = void 0;
      priv.pressed = false;
      priv.backlightWidth = 0;

      (0, _element.removeClass)(this.hot.rootElement, [CSS_ON_MOVING, CSS_SHOW_UI, CSS_AFTER_SELECTION]);

      if (this.hot.selection.selectedHeader.cols) {
        (0, _element.addClass)(this.hot.rootElement, CSS_AFTER_SELECTION);
      }
      if (priv.columnsToMove.length < 1 || priv.target.col === void 0 || priv.columnsToMove.indexOf(priv.target.col) > -1) {
        return;
      }

      this.moveColumns(priv.columnsToMove, priv.target.col);
      this.persistentStateSave();
      this.hot.render();
      this.hot.view.wt.wtOverlays.adjustElementsSize(true);

      if (!priv.disallowMoving) {
        var selectionStart = this.columnsMapper.getIndexByValue(priv.columnsToMove[0]);
        var selectionEnd = this.columnsMapper.getIndexByValue(priv.columnsToMove[priv.columnsToMove.length - 1]);
        this.changeSelection(selectionStart, selectionEnd);
      }

      priv.columnsToMove.length = 0;
    }

    /**
     * `afterScrollHorizontally` hook callback. Fired the table was scrolled horizontally.
     *
     * @private
     */

  }, {
    key: 'onAfterScrollVertically',
    value: function onAfterScrollVertically() {
      var wtTable = this.hot.view.wt.wtTable;
      var headerHeight = wtTable.getColumnHeaderHeight(0) + 1;
      var scrollTop = wtTable.holder.scrollTop;
      var posTop = headerHeight + scrollTop;

      this.backlight.setPosition(posTop);
      this.backlight.setSize(null, wtTable.hider.offsetHeight - posTop);
    }

    /**
     * `afterCreateCol` hook callback.
     *
     * @private
     * @param {Number} index Visual index of the created column.
     * @param {Number} amount Amount of created columns.
     */

  }, {
    key: 'onAfterCreateCol',
    value: function onAfterCreateCol(index, amount) {
      this.columnsMapper.shiftItems(index, amount);
    }

    /**
     * On before remove column listener.
     *
     * @private
     * @param {Number} index Visual column index.
     * @param {Number} amount Defines how many columns removed.
     */

  }, {
    key: 'onBeforeRemoveCol',
    value: function onBeforeRemoveCol(index, amount) {
      var _this5 = this;

      this.removedColumns.length = 0;

      if (index !== false) {
        // Collect physical row index.
        (0, _number.rangeEach)(index, index + amount - 1, function (removedIndex) {
          _this5.removedColumns.push(_this5.hot.runHooks('modifyCol', removedIndex, _this5.pluginName));
        });
      }
    }

    /**
     * `afterRemoveCol` hook callback.
     *
     * @private
     * @param {Number} index Visual column index of the removed column.
     * @param {Number} amount Amount of removed columns.
     */

  }, {
    key: 'onAfterRemoveCol',
    value: function onAfterRemoveCol(index, amount) {
      this.columnsMapper.unshiftItems(this.removedColumns);
    }

    /**
     * `afterLoadData` hook callback.
     *
     * @private
     * @param {Boolean} firstTime True if that was loading data during the initialization.
     */

  }, {
    key: 'onAfterLoadData',
    value: function onAfterLoadData(firstTime) {
      this.updateColumnsMapper();
    }

    /**
     * 'modifyRow' hook callback.
     *
     * @private
     * @param {Number} column Visual column index.
     * @returns {Number} Physical column index.
     */

  }, {
    key: 'onModifyCol',
    value: function onModifyCol(column, source) {
      if (source !== this.pluginName) {
        // ugly fix for try to insert new, needed columns after pasting data
        var columnInMapper = this.columnsMapper.getValueByIndex(column);
        column = columnInMapper === null ? column : columnInMapper;
      }

      return column;
    }

    /**
     * 'unmodifyCol' hook callback.
     *
     * @private
     * @param {Number} column Physical column index.
     * @returns {Number} Visual column index.
     */

  }, {
    key: 'onUnmodifyCol',
    value: function onUnmodifyCol(column) {
      var indexInMapper = this.columnsMapper.getIndexByValue(column);

      return indexInMapper === null ? column : indexInMapper;
    }

    /**
     * `afterPluginsInitialized` hook callback.
     *
     * @private
     */

  }, {
    key: 'onAfterPluginsInitialized',
    value: function onAfterPluginsInitialized() {
      this.updateColumnsMapper();
      this.initialSettings();
      this.backlight.build();
      this.guideline.build();
    }

    /**
     * Destroy plugin instance.
     */

  }, {
    key: 'destroy',
    value: function destroy() {
      this.backlight.destroy();
      this.guideline.destroy();

      _get(ManualColumnMove.prototype.__proto__ || Object.getPrototypeOf(ManualColumnMove.prototype), 'destroy', this).call(this);
    }
  }]);

  return ManualColumnMove;
}(_base2.default);

(0, _plugins.registerPlugin)('ManualColumnMove', ManualColumnMove);

exports.default = ManualColumnMove;

/***/ }),
/* 365 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


exports.__esModule = true;

var _createClass = 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); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

var _get = function get(object, property, receiver) { if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ("value" in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } };

var _base = __webpack_require__(266);

var _base2 = _interopRequireDefault(_base);

var _element = __webpack_require__(0);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }

function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }

var CSS_CLASSNAME = 'ht__manualColumnMove--backlight';

/**
 * @class BacklightUI
 * @util
 */

var BacklightUI = function (_BaseUI) {
  _inherits(BacklightUI, _BaseUI);

  function BacklightUI() {
    _classCallCheck(this, BacklightUI);

    return _possibleConstructorReturn(this, (BacklightUI.__proto__ || Object.getPrototypeOf(BacklightUI)).apply(this, arguments));
  }

  _createClass(BacklightUI, [{
    key: 'build',

    /**
     * Custom className on build process.
     */
    value: function build() {
      _get(BacklightUI.prototype.__proto__ || Object.getPrototypeOf(BacklightUI.prototype), 'build', this).call(this);

      (0, _element.addClass)(this._element, CSS_CLASSNAME);
    }
  }]);

  return BacklightUI;
}(_base2.default);

exports.default = BacklightUI;

/***/ }),
/* 366 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


exports.__esModule = true;

var _createClass = 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); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

var _get = function get(object, property, receiver) { if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ("value" in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } };

var _base = __webpack_require__(266);

var _base2 = _interopRequireDefault(_base);

var _element = __webpack_require__(0);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }

function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }

var CSS_CLASSNAME = 'ht__manualColumnMove--guideline';

/**
 * @class GuidelineUI
 * @util
 */

var GuidelineUI = function (_BaseUI) {
  _inherits(GuidelineUI, _BaseUI);

  function GuidelineUI() {
    _classCallCheck(this, GuidelineUI);

    return _possibleConstructorReturn(this, (GuidelineUI.__proto__ || Object.getPrototypeOf(GuidelineUI)).apply(this, arguments));
  }

  _createClass(GuidelineUI, [{
    key: 'build',

    /**
     * Custom className on build process.
     */
    value: function build() {
      _get(GuidelineUI.prototype.__proto__ || Object.getPrototypeOf(GuidelineUI.prototype), 'build', this).call(this);

      (0, _element.addClass)(this._element, CSS_CLASSNAME);
    }
  }]);

  return GuidelineUI;
}(_base2.default);

exports.default = GuidelineUI;

/***/ }),
/* 367 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


exports.__esModule = true;

var _createClass = 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); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

var _get = function get(object, property, receiver) { if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ("value" in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } };

var _base = __webpack_require__(16);

var _base2 = _interopRequireDefault(_base);

var _element = __webpack_require__(0);

var _eventManager = __webpack_require__(4);

var _eventManager2 = _interopRequireDefault(_eventManager);

var _event = __webpack_require__(7);

var _array = __webpack_require__(2);

var _number = __webpack_require__(5);

var _plugins = __webpack_require__(9);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }

function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }

// Developer note! Whenever you make a change in this file, make an analogous change in manualRowResize.js

/**
 * @description
 * ManualColumnResize Plugin.
 *
 * Has 2 UI components:
 * - handle - the draggable element that sets the desired width of the column.
 * - guide - the helper guide that shows the desired width as a vertical guide.
 *
 * @plugin ManualColumnResize
 */
var ManualColumnResize = function (_BasePlugin) {
  _inherits(ManualColumnResize, _BasePlugin);

  function ManualColumnResize(hotInstance) {
    _classCallCheck(this, ManualColumnResize);

    var _this = _possibleConstructorReturn(this, (ManualColumnResize.__proto__ || Object.getPrototypeOf(ManualColumnResize)).call(this, hotInstance));

    _this.currentTH = null;
    _this.currentCol = null;
    _this.selectedCols = [];
    _this.currentWidth = null;
    _this.newSize = null;
    _this.startY = null;
    _this.startWidth = null;
    _this.startOffset = null;
    _this.handle = document.createElement('DIV');
    _this.guide = document.createElement('DIV');
    _this.eventManager = new _eventManager2.default(_this);
    _this.pressed = null;
    _this.dblclick = 0;
    _this.autoresizeTimeout = null;
    _this.manualColumnWidths = [];

    (0, _element.addClass)(_this.handle, 'manualColumnResizer');
    (0, _element.addClass)(_this.guide, 'manualColumnResizerGuide');
    return _this;
  }

  /**
   * Check if the plugin is enabled in the handsontable settings.
   *
   * @returns {Boolean}
   */


  _createClass(ManualColumnResize, [{
    key: 'isEnabled',
    value: function isEnabled() {
      return this.hot.getSettings().manualColumnResize;
    }

    /**
     * Enable plugin for this Handsontable instance.
     */

  }, {
    key: 'enablePlugin',
    value: function enablePlugin() {
      var _this2 = this;

      if (this.enabled) {
        return;
      }

      this.manualColumnWidths = [];
      var initialColumnWidth = this.hot.getSettings().manualColumnResize;
      var loadedManualColumnWidths = this.loadManualColumnWidths();

      this.addHook('modifyColWidth', function (width, col) {
        return _this2.onModifyColWidth(width, col);
      });
      this.addHook('beforeStretchingColumnWidth', function (stretchedWidth, column) {
        return _this2.onBeforeStretchingColumnWidth(stretchedWidth, column);
      });
      this.addHook('beforeColumnResize', function (currentColumn, newSize, isDoubleClick) {
        return _this2.onBeforeColumnResize(currentColumn, newSize, isDoubleClick);
      });

      if (typeof loadedManualColumnWidths != 'undefined') {
        this.manualColumnWidths = loadedManualColumnWidths;
      } else if (Array.isArray(initialColumnWidth)) {
        this.manualColumnWidths = initialColumnWidth;
      } else {
        this.manualColumnWidths = [];
      }

      // Handsontable.hooks.register('beforeColumnResize');
      // Handsontable.hooks.register('afterColumnResize');

      this.bindEvents();

      _get(ManualColumnResize.prototype.__proto__ || Object.getPrototypeOf(ManualColumnResize.prototype), 'enablePlugin', this).call(this);
    }

    /**
     * Updates the plugin to use the latest options you have specified.
     */

  }, {
    key: 'updatePlugin',
    value: function updatePlugin() {
      var initialColumnWidth = this.hot.getSettings().manualColumnResize;

      if (Array.isArray(initialColumnWidth)) {
        this.manualColumnWidths = initialColumnWidth;
      } else if (!initialColumnWidth) {
        this.manualColumnWidths = [];
      }
    }

    /**
     * Disable plugin for this Handsontable instance.
     */

  }, {
    key: 'disablePlugin',
    value: function disablePlugin() {
      _get(ManualColumnResize.prototype.__proto__ || Object.getPrototypeOf(ManualColumnResize.prototype), 'disablePlugin', this).call(this);
    }

    /**
     * Save the current sizes using the persistentState plugin.
     */

  }, {
    key: 'saveManualColumnWidths',
    value: function saveManualColumnWidths() {
      this.hot.runHooks('persistentStateSave', 'manualColumnWidths', this.manualColumnWidths);
    }

    /**
     * Load the previously saved sizes using the persistentState plugin.
     *
     * @returns {Array}
     */

  }, {
    key: 'loadManualColumnWidths',
    value: function loadManualColumnWidths() {
      var storedState = {};

      this.hot.runHooks('persistentStateLoad', 'manualColumnWidths', storedState);

      return storedState.value;
    }

    /**
     * Set the resize handle position.
     *
     * @param {HTMLCellElement} TH TH HTML element.
     */

  }, {
    key: 'setupHandlePosition',
    value: function setupHandlePosition(TH) {
      var _this3 = this;

      if (!TH.parentNode) {
        return false;
      }

      this.currentTH = TH;

      var col = this.hot.view.wt.wtTable.getCoords(TH).col; // getCoords returns CellCoords
      var headerHeight = (0, _element.outerHeight)(this.currentTH);

      if (col >= 0) {
        // if not col header
        var box = this.currentTH.getBoundingClientRect();

        this.currentCol = col;
        this.selectedCols = [];

        if (this.hot.selection.isSelected() && this.hot.selection.selectedHeader.cols) {
          var _hot$getSelectedRange = this.hot.getSelectedRange(),
              from = _hot$getSelectedRange.from,
              to = _hot$getSelectedRange.to;

          var start = from.col;
          var end = to.col;

          if (start >= end) {
            start = to.col;
            end = from.col;
          }

          if (this.currentCol >= start && this.currentCol <= end) {
            (0, _number.rangeEach)(start, end, function (i) {
              return _this3.selectedCols.push(i);
            });
          } else {
            this.selectedCols.push(this.currentCol);
          }
        } else {
          this.selectedCols.push(this.currentCol);
        }

        this.startOffset = box.left - 6;
        this.startWidth = parseInt(box.width, 10);
        this.handle.style.top = box.top + 'px';
        this.handle.style.left = this.startOffset + this.startWidth + 'px';
        this.handle.style.height = headerHeight + 'px';
        this.hot.rootElement.appendChild(this.handle);
      }
    }

    /**
     * Refresh the resize handle position.
     */

  }, {
    key: 'refreshHandlePosition',
    value: function refreshHandlePosition() {
      this.handle.style.left = this.startOffset + this.currentWidth + 'px';
    }

    /**
     * Set the resize guide position.
     */

  }, {
    key: 'setupGuidePosition',
    value: function setupGuidePosition() {
      var handleHeight = parseInt((0, _element.outerHeight)(this.handle), 10);
      var handleBottomPosition = parseInt(this.handle.style.top, 10) + handleHeight;
      var maximumVisibleElementHeight = parseInt(this.hot.view.maximumVisibleElementHeight(0), 10);

      (0, _element.addClass)(this.handle, 'active');
      (0, _element.addClass)(this.guide, 'active');

      this.guide.style.top = handleBottomPosition + 'px';
      this.guide.style.left = this.handle.style.left;
      this.guide.style.height = maximumVisibleElementHeight - handleHeight + 'px';
      this.hot.rootElement.appendChild(this.guide);
    }

    /**
     * Refresh the resize guide position.
     */

  }, {
    key: 'refreshGuidePosition',
    value: function refreshGuidePosition() {
      this.guide.style.left = this.handle.style.left;
    }

    /**
     * Hide both the resize handle and resize guide.
     */

  }, {
    key: 'hideHandleAndGuide',
    value: function hideHandleAndGuide() {
      (0, _element.removeClass)(this.handle, 'active');
      (0, _element.removeClass)(this.guide, 'active');
    }

    /**
     * Check if provided element is considered a column header.
     *
     * @param {HTMLElement} element HTML element.
     * @returns {Boolean}
     */

  }, {
    key: 'checkIfColumnHeader',
    value: function checkIfColumnHeader(element) {
      if (element != this.hot.rootElement) {
        var parent = element.parentNode;

        if (parent.tagName === 'THEAD') {
          return true;
        }

        return this.checkIfColumnHeader(parent);
      }

      return false;
    }

    /**
     * Get the TH element from the provided element.
     *
     * @param {HTMLElement} element HTML element.
     * @returns {HTMLElement}
     */

  }, {
    key: 'getTHFromTargetElement',
    value: function getTHFromTargetElement(element) {
      if (element.tagName != 'TABLE') {
        if (element.tagName == 'TH') {
          return element;
        }
        return this.getTHFromTargetElement(element.parentNode);
      }

      return null;
    }

    /**
     * 'mouseover' event callback - set the handle position.
     *
     * @private
     * @param {MouseEvent} event
     */

  }, {
    key: 'onMouseOver',
    value: function onMouseOver(event) {
      if (this.checkIfColumnHeader(event.target)) {
        var th = this.getTHFromTargetElement(event.target);

        if (!th) {
          return;
        }

        var colspan = th.getAttribute('colspan');

        if (th && (colspan === null || colspan === 1)) {
          if (!this.pressed) {
            this.setupHandlePosition(th);
          }
        }
      }
    }

    /**
     * Auto-size row after doubleclick - callback.
     *
     * @private
     */

  }, {
    key: 'afterMouseDownTimeout',
    value: function afterMouseDownTimeout() {
      var _this4 = this;

      var render = function render() {
        _this4.hot.forceFullRender = true;
        _this4.hot.view.render(); // updates all
        _this4.hot.view.wt.wtOverlays.adjustElementsSize(true);
      };
      var resize = function resize(selectedCol, forceRender) {
        var hookNewSize = _this4.hot.runHooks('beforeColumnResize', selectedCol, _this4.newSize, true);

        if (hookNewSize !== void 0) {
          _this4.newSize = hookNewSize;
        }

        if (_this4.hot.getSettings().stretchH === 'all') {
          _this4.clearManualSize(selectedCol);
        } else {
          _this4.setManualSize(selectedCol, _this4.newSize); // double click sets by auto row size plugin
        }

        if (forceRender) {
          render();
        }

        _this4.saveManualColumnWidths();

        _this4.hot.runHooks('afterColumnResize', selectedCol, _this4.newSize, true);
      };

      if (this.dblclick >= 2) {
        var selectedColsLength = this.selectedCols.length;

        if (selectedColsLength > 1) {
          (0, _array.arrayEach)(this.selectedCols, function (selectedCol) {
            resize(selectedCol);
          });
          render();
        } else {
          (0, _array.arrayEach)(this.selectedCols, function (selectedCol) {
            resize(selectedCol, true);
          });
        }
      }
      this.dblclick = 0;
      this.autoresizeTimeout = null;
    }

    /**
     * 'mousedown' event callback.
     *
     * @private
     * @param {MouseEvent} e
     */

  }, {
    key: 'onMouseDown',
    value: function onMouseDown(event) {
      var _this5 = this;

      if ((0, _element.hasClass)(event.target, 'manualColumnResizer')) {
        this.setupGuidePosition();
        this.pressed = this.hot;

        if (this.autoresizeTimeout === null) {
          this.autoresizeTimeout = setTimeout(function () {
            return _this5.afterMouseDownTimeout();
          }, 500);

          this.hot._registerTimeout(this.autoresizeTimeout);
        }
        this.dblclick++;

        this.startX = (0, _event.pageX)(event);
        this.newSize = this.startWidth;
      }
    }

    /**
     * 'mousemove' event callback - refresh the handle and guide positions, cache the new column width.
     *
     * @private
     * @param {MouseEvent} e
     */

  }, {
    key: 'onMouseMove',
    value: function onMouseMove(event) {
      var _this6 = this;

      if (this.pressed) {
        this.currentWidth = this.startWidth + ((0, _event.pageX)(event) - this.startX);

        (0, _array.arrayEach)(this.selectedCols, function (selectedCol) {
          _this6.newSize = _this6.setManualSize(selectedCol, _this6.currentWidth);
        });

        this.refreshHandlePosition();
        this.refreshGuidePosition();
      }
    }

    /**
     * 'mouseup' event callback - apply the column resizing.
     *
     * @private
     * @param {MouseEvent} e
     */

  }, {
    key: 'onMouseUp',
    value: function onMouseUp(event) {
      var _this7 = this;

      var render = function render() {
        _this7.hot.forceFullRender = true;
        _this7.hot.view.render(); // updates all
        _this7.hot.view.wt.wtOverlays.adjustElementsSize(true);
      };
      var resize = function resize(selectedCol, forceRender) {
        _this7.hot.runHooks('beforeColumnResize', selectedCol, _this7.newSize);

        if (forceRender) {
          render();
        }

        _this7.saveManualColumnWidths();

        _this7.hot.runHooks('afterColumnResize', selectedCol, _this7.newSize);
      };

      if (this.pressed) {
        this.hideHandleAndGuide();
        this.pressed = false;

        if (this.newSize != this.startWidth) {
          var selectedColsLength = this.selectedCols.length;

          if (selectedColsLength > 1) {
            (0, _array.arrayEach)(this.selectedCols, function (selectedCol) {
              resize(selectedCol);
            });
            render();
          } else {
            (0, _array.arrayEach)(this.selectedCols, function (selectedCol) {
              resize(selectedCol, true);
            });
          }
        }

        this.setupHandlePosition(this.currentTH);
      }
    }

    /**
     * Bind the mouse events.
     *
     * @private
     */

  }, {
    key: 'bindEvents',
    value: function bindEvents() {
      var _this8 = this;

      this.eventManager.addEventListener(this.hot.rootElement, 'mouseover', function (e) {
        return _this8.onMouseOver(e);
      });
      this.eventManager.addEventListener(this.hot.rootElement, 'mousedown', function (e) {
        return _this8.onMouseDown(e);
      });
      this.eventManager.addEventListener(window, 'mousemove', function (e) {
        return _this8.onMouseMove(e);
      });
      this.eventManager.addEventListener(window, 'mouseup', function (e) {
        return _this8.onMouseUp(e);
      });
    }

    /**
     * Cache the current column width.
     *
     * @param {Number} column Visual column index.
     * @param {Number} width Column width.
     * @returns {Number}
     */

  }, {
    key: 'setManualSize',
    value: function setManualSize(column, width) {
      width = Math.max(width, 20);

      /**
       *  We need to run col through modifyCol hook, in case the order of displayed columns is different than the order
       *  in data source. For instance, this order can be modified by manualColumnMove plugin.
       */
      column = this.hot.runHooks('modifyCol', column);

      this.manualColumnWidths[column] = width;

      return width;
    }

    /**
     * Clear cache for the current column index.
     *
     * @param {Number} column Visual column index.
     */

  }, {
    key: 'clearManualSize',
    value: function clearManualSize(column) {
      column = this.hot.runHooks('modifyCol', column);

      this.manualColumnWidths[column] = void 0;
    }

    /**
     * Modify the provided column width, based on the plugin settings
     *
     * @private
     * @param {Number} width Column width.
     * @param {Number} column Visual column index.
     * @returns {Number}
     */

  }, {
    key: 'onModifyColWidth',
    value: function onModifyColWidth(width, column) {
      if (this.enabled) {
        column = this.hot.runHooks('modifyCol', column);

        if (this.hot.getSettings().manualColumnResize && this.manualColumnWidths[column]) {
          return this.manualColumnWidths[column];
        }
      }

      return width;
    }

    /**
     * Modify the provided column stretched width. This hook decides if specified column should be stretched or not.
     *
     * @private
     * @param {Number} stretchedWidth Stretched width.
     * @param {Number} column Physical column index.
     * @returns {Number}
     */

  }, {
    key: 'onBeforeStretchingColumnWidth',
    value: function onBeforeStretchingColumnWidth(stretchedWidth, column) {
      var width = this.manualColumnWidths[column];

      if (width === void 0) {
        width = stretchedWidth;
      }

      return width;
    }

    /**
     * `beforeColumnResize` hook callback.
     *
     * @private
     * @param {Number} currentColumn Index of the resized column.
     * @param {Number} newSize Calculated new column width.
     * @param {Boolean} isDoubleClick Flag that determines whether there was a double-click.
     */

  }, {
    key: 'onBeforeColumnResize',
    value: function onBeforeColumnResize() {
      // clear the header height cache information
      this.hot.view.wt.wtViewport.hasOversizedColumnHeadersMarked = {};
    }
  }]);

  return ManualColumnResize;
}(_base2.default);

(0, _plugins.registerPlugin)('manualColumnResize', ManualColumnResize);

exports.default = ManualColumnResize;

/***/ }),
/* 368 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


exports.__esModule = true;

var _createClass = 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); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

var _get = function get(object, property, receiver) { if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ("value" in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } };

var _base = __webpack_require__(16);

var _base2 = _interopRequireDefault(_base);

var _pluginHooks = __webpack_require__(11);

var _pluginHooks2 = _interopRequireDefault(_pluginHooks);

var _array = __webpack_require__(2);

var _element = __webpack_require__(0);

var _number = __webpack_require__(5);

var _eventManager = __webpack_require__(4);

var _eventManager2 = _interopRequireDefault(_eventManager);

var _plugins = __webpack_require__(9);

var _rowsMapper = __webpack_require__(369);

var _rowsMapper2 = _interopRequireDefault(_rowsMapper);

var _backlight = __webpack_require__(370);

var _backlight2 = _interopRequireDefault(_backlight);

var _guideline = __webpack_require__(371);

var _guideline2 = _interopRequireDefault(_guideline);

var _src = __webpack_require__(14);

__webpack_require__(303);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }

function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }

_pluginHooks2.default.getSingleton().register('beforeRowMove');
_pluginHooks2.default.getSingleton().register('afterRowMove');
_pluginHooks2.default.getSingleton().register('unmodifyRow');

var privatePool = new WeakMap();
var CSS_PLUGIN = 'ht__manualRowMove';
var CSS_SHOW_UI = 'show-ui';
var CSS_ON_MOVING = 'on-moving--rows';
var CSS_AFTER_SELECTION = 'after-selection--rows';

/**
 * @plugin ManualRowMove
 *
 * @description
 * This plugin allows to change rows order.
 *
 * API:
 * - moveRow - move single row to the new position.
 * - moveRows - move many rows (as an array of indexes) to the new position.
 *
 * If you want apply visual changes, you have to call manually the render() method on the instance of handsontable.
 *
 * UI components:
 * - backlight - highlight of selected rows.
 * - guideline - line which shows where rows has been moved.
 *
 * @class ManualRowMove
 * @plugin ManualRowMove
 */

var ManualRowMove = function (_BasePlugin) {
  _inherits(ManualRowMove, _BasePlugin);

  function ManualRowMove(hotInstance) {
    _classCallCheck(this, ManualRowMove);

    /**
     * Set up WeakMap of plugin to sharing private parameters;
     */
    var _this = _possibleConstructorReturn(this, (ManualRowMove.__proto__ || Object.getPrototypeOf(ManualRowMove)).call(this, hotInstance));

    privatePool.set(_this, {
      rowsToMove: [],
      pressed: void 0,
      disallowMoving: void 0,
      target: {
        eventPageY: void 0,
        coords: void 0,
        TD: void 0,
        row: void 0
      }
    });

    /**
     * List of last removed row indexes.
     *
     * @type {Array}
     */
    _this.removedRows = [];
    /**
     * Object containing visual row indexes mapped to data source indexes.
     *
     * @type {RowsMapper}
     */
    _this.rowsMapper = new _rowsMapper2.default(_this);
    /**
     * Event Manager object.
     *
     * @type {Object}
     */
    _this.eventManager = new _eventManager2.default(_this);
    /**
     * Backlight UI object.
     *
     * @type {Object}
     */
    _this.backlight = new _backlight2.default(hotInstance);
    /**
     * Guideline UI object.
     *
     * @type {Object}
     */
    _this.guideline = new _guideline2.default(hotInstance);
    return _this;
  }

  /**
   * Check if plugin is enabled.
   *
   * @returns {Boolean}
   */


  _createClass(ManualRowMove, [{
    key: 'isEnabled',
    value: function isEnabled() {
      return !!this.hot.getSettings().manualRowMove;
    }

    /**
     * Enable the plugin.
     */

  }, {
    key: 'enablePlugin',
    value: function enablePlugin() {
      var _this2 = this;

      if (this.enabled) {
        return;
      }

      this.addHook('beforeOnCellMouseDown', function (event, coords, TD, blockCalculations) {
        return _this2.onBeforeOnCellMouseDown(event, coords, TD, blockCalculations);
      });
      this.addHook('beforeOnCellMouseOver', function (event, coords, TD, blockCalculations) {
        return _this2.onBeforeOnCellMouseOver(event, coords, TD, blockCalculations);
      });
      this.addHook('afterScrollHorizontally', function () {
        return _this2.onAfterScrollHorizontally();
      });
      this.addHook('modifyRow', function (row, source) {
        return _this2.onModifyRow(row, source);
      });
      this.addHook('beforeRemoveRow', function (index, amount) {
        return _this2.onBeforeRemoveRow(index, amount);
      });
      this.addHook('afterRemoveRow', function (index, amount) {
        return _this2.onAfterRemoveRow(index, amount);
      });
      this.addHook('afterCreateRow', function (index, amount) {
        return _this2.onAfterCreateRow(index, amount);
      });
      this.addHook('afterLoadData', function (firstTime) {
        return _this2.onAfterLoadData(firstTime);
      });
      this.addHook('beforeColumnSort', function (column, order) {
        return _this2.onBeforeColumnSort(column, order);
      });
      this.addHook('unmodifyRow', function (row) {
        return _this2.onUnmodifyRow(row);
      });

      this.registerEvents();

      // TODO: move adding plugin classname to BasePlugin.
      (0, _element.addClass)(this.hot.rootElement, CSS_PLUGIN);

      _get(ManualRowMove.prototype.__proto__ || Object.getPrototypeOf(ManualRowMove.prototype), 'enablePlugin', this).call(this);
    }

    /**
     * Updates the plugin to use the latest options you have specified.
     */

  }, {
    key: 'updatePlugin',
    value: function updatePlugin() {
      this.disablePlugin();
      this.enablePlugin();

      this.onAfterPluginsInitialized();

      _get(ManualRowMove.prototype.__proto__ || Object.getPrototypeOf(ManualRowMove.prototype), 'updatePlugin', this).call(this);
    }

    /**
     * Disable plugin for this Handsontable instance.
     */

  }, {
    key: 'disablePlugin',
    value: function disablePlugin() {
      var pluginSettings = this.hot.getSettings().manualRowMove;

      if (Array.isArray(pluginSettings)) {
        this.rowsMapper.clearMap();
      }

      (0, _element.removeClass)(this.hot.rootElement, CSS_PLUGIN);

      this.unregisterEvents();
      this.backlight.destroy();
      this.guideline.destroy();

      _get(ManualRowMove.prototype.__proto__ || Object.getPrototypeOf(ManualRowMove.prototype), 'disablePlugin', this).call(this);
    }

    /**
     * Move a single row.
     *
     * @param {Number} row Visual row index to be moved.
     * @param {Number} target Visual row index being a target for the moved row.
     */

  }, {
    key: 'moveRow',
    value: function moveRow(row, target) {
      this.moveRows([row], target);
    }

    /**
     * Move multiple rows.
     *
     * @param {Array} rows Array of visual row indexes to be moved.
     * @param {Number} target Visual row index being a target for the moved rows.
     */

  }, {
    key: 'moveRows',
    value: function moveRows(rows, target) {
      var _this3 = this;

      var priv = privatePool.get(this);
      var beforeMoveHook = this.hot.runHooks('beforeRowMove', rows, target);

      priv.disallowMoving = beforeMoveHook === false;

      if (!priv.disallowMoving) {
        // first we need to rewrite an visual indexes to physical for save reference after move
        (0, _array.arrayEach)(rows, function (row, index, array) {
          array[index] = _this3.rowsMapper.getValueByIndex(row);
        });

        // next, when we have got an physical indexes, we can move rows
        (0, _array.arrayEach)(rows, function (row, index) {
          var actualPosition = _this3.rowsMapper.getIndexByValue(row);

          if (actualPosition !== target) {
            _this3.rowsMapper.moveRow(actualPosition, target + index);
          }
        });

        // after moving we have to clear rowsMapper from null entries
        this.rowsMapper.clearNull();
      }

      this.hot.runHooks('afterRowMove', rows, target);
    }

    /**
     * Correct the cell selection after the move action. Fired only when action was made with a mouse.
     * That means that changing the row order using the API won't correct the selection.
     *
     * @private
     * @param {Number} startRow Visual row index for the start of the selection.
     * @param {Number} endRow Visual row index for the end of the selection.
     */

  }, {
    key: 'changeSelection',
    value: function changeSelection(startRow, endRow) {
      var selection = this.hot.selection;
      var lastColIndex = this.hot.countCols() - 1;

      selection.setRangeStartOnly(new _src.CellCoords(startRow, 0));
      selection.setRangeEnd(new _src.CellCoords(endRow, lastColIndex), false);
    }

    /**
     * Get the sum of the heights of rows in the provided range.
     *
     * @private
     * @param {Number} from Visual row index.
     * @param {Number} to Visual row index.
     * @returns {Number}
     */

  }, {
    key: 'getRowsHeight',
    value: function getRowsHeight(from, to) {
      var height = 0;

      for (var i = from; i < to; i++) {
        var rowHeight = this.hot.view.wt.wtTable.getRowHeight(i) || 23;

        height += rowHeight;
      }

      return height;
    }

    /**
     * Load initial settings when persistent state is saved or when plugin was initialized as an array.
     *
     * @private
     */

  }, {
    key: 'initialSettings',
    value: function initialSettings() {
      var pluginSettings = this.hot.getSettings().manualRowMove;

      if (Array.isArray(pluginSettings)) {
        this.moveRows(pluginSettings, 0);
      } else if (pluginSettings !== void 0) {
        var persistentState = this.persistentStateLoad();

        if (persistentState.length) {
          this.moveRows(persistentState, 0);
        }
      }
    }

    /**
     * Check if the provided row is in the fixedRowsTop section.
     *
     * @private
     * @param {Number} row Visual row index to check.
     * @returns {Boolean}
     */

  }, {
    key: 'isFixedRowTop',
    value: function isFixedRowTop(row) {
      return row < this.hot.getSettings().fixedRowsTop;
    }

    /**
     * Check if the provided row is in the fixedRowsBottom section.
     *
     * @private
     * @param {Number} row Visual row index to check.
     * @returns {Boolean}
     */

  }, {
    key: 'isFixedRowBottom',
    value: function isFixedRowBottom(row) {
      return row > this.hot.getSettings().fixedRowsBottom;
    }

    /**
     * Save the manual row positions to the persistent state.
     *
     * @private
     */

  }, {
    key: 'persistentStateSave',
    value: function persistentStateSave() {
      this.hot.runHooks('persistentStateSave', 'manualRowMove', this.rowsMapper._arrayMap);
    }

    /**
     * Load the manual row positions from the persistent state.
     *
     * @private
     * @returns {Array} Stored state.
     */

  }, {
    key: 'persistentStateLoad',
    value: function persistentStateLoad() {
      var storedState = {};

      this.hot.runHooks('persistentStateLoad', 'manualRowMove', storedState);

      return storedState.value ? storedState.value : [];
    }

    /**
     * Prepare array of indexes based on actual selection.
     *
     * @private
     * @returns {Array}
     */

  }, {
    key: 'prepareRowsToMoving',
    value: function prepareRowsToMoving() {
      var selection = this.hot.getSelectedRange();
      var selectedRows = [];

      if (!selection) {
        return selectedRows;
      }

      var from = selection.from,
          to = selection.to;

      var start = Math.min(from.row, to.row);
      var end = Math.max(from.row, to.row);

      (0, _number.rangeEach)(start, end, function (i) {
        selectedRows.push(i);
      });

      return selectedRows;
    }

    /**
     * Update the UI visual position.
     *
     * @private
     */

  }, {
    key: 'refreshPositions',
    value: function refreshPositions() {
      var priv = privatePool.get(this);
      var coords = priv.target.coords;
      var firstVisible = this.hot.view.wt.wtTable.getFirstVisibleRow();
      var lastVisible = this.hot.view.wt.wtTable.getLastVisibleRow();
      var fixedRows = this.hot.getSettings().fixedRowsTop;
      var countRows = this.hot.countRows();

      if (coords.row < fixedRows && firstVisible > 0) {
        this.hot.scrollViewportTo(firstVisible - 1);
      }
      if (coords.row >= lastVisible && lastVisible < countRows) {
        this.hot.scrollViewportTo(lastVisible + 1, undefined, true);
      }

      var wtTable = this.hot.view.wt.wtTable;
      var TD = priv.target.TD;
      var rootElementOffset = (0, _element.offset)(this.hot.rootElement);
      var tdOffsetTop = this.hot.view.THEAD.offsetHeight + this.getRowsHeight(0, coords.row);
      var mouseOffsetTop = priv.target.eventPageY - rootElementOffset.top + wtTable.holder.scrollTop;
      var hiderHeight = wtTable.hider.offsetHeight;
      var tbodyOffsetTop = wtTable.TBODY.offsetTop;
      var backlightElemMarginTop = this.backlight.getOffset().top;
      var backlightElemHeight = this.backlight.getSize().height;

      if (this.isFixedRowTop(coords.row)) {
        tdOffsetTop += wtTable.holder.scrollTop;
      }

      // todo: fixedRowsBottom
      // if (this.isFixedRowBottom(coords.row)) {
      //
      // }

      if (coords.row < 0) {
        // if hover on colHeader
        priv.target.row = firstVisible > 0 ? firstVisible - 1 : firstVisible;
      } else if (TD.offsetHeight / 2 + tdOffsetTop <= mouseOffsetTop) {
        // if hover on lower part of TD
        priv.target.row = coords.row + 1;
        // unfortunately first row is bigger than rest
        tdOffsetTop += coords.row === 0 ? TD.offsetHeight - 1 : TD.offsetHeight;
      } else {
        // elsewhere on table
        priv.target.row = coords.row;
      }

      var backlightTop = mouseOffsetTop;
      var guidelineTop = tdOffsetTop;

      if (mouseOffsetTop + backlightElemHeight + backlightElemMarginTop >= hiderHeight) {
        // prevent display backlight below table
        backlightTop = hiderHeight - backlightElemHeight - backlightElemMarginTop;
      } else if (mouseOffsetTop + backlightElemMarginTop < tbodyOffsetTop) {
        // prevent display above below table
        backlightTop = tbodyOffsetTop + Math.abs(backlightElemMarginTop);
      }

      if (tdOffsetTop >= hiderHeight - 1) {
        // prevent display guideline below table
        guidelineTop = hiderHeight - 1;
      }

      var topOverlayHeight = 0;
      if (this.hot.view.wt.wtOverlays.topOverlay) {
        topOverlayHeight = this.hot.view.wt.wtOverlays.topOverlay.clone.wtTable.TABLE.offsetHeight;
      }

      if (coords.row >= fixedRows && guidelineTop - wtTable.holder.scrollTop < topOverlayHeight) {
        this.hot.scrollViewportTo(coords.row);
      }

      this.backlight.setPosition(backlightTop);
      this.guideline.setPosition(guidelineTop);
    }

    /**
     * This method checks arrayMap from rowsMapper and updates the rowsMapper if it's necessary.
     *
     * @private
     */

  }, {
    key: 'updateRowsMapper',
    value: function updateRowsMapper() {
      var countRows = this.hot.countSourceRows();
      var rowsMapperLen = this.rowsMapper._arrayMap.length;

      if (rowsMapperLen === 0) {
        this.rowsMapper.createMap(countRows || this.hot.getSettings().startRows);
      } else if (rowsMapperLen < countRows) {
        var diff = countRows - rowsMapperLen;

        this.rowsMapper.insertItems(rowsMapperLen, diff);
      } else if (rowsMapperLen > countRows) {
        var maxIndex = countRows - 1;
        var rowsToRemove = [];

        (0, _array.arrayEach)(this.rowsMapper._arrayMap, function (value, index, array) {
          if (value > maxIndex) {
            rowsToRemove.push(index);
          }
        });

        this.rowsMapper.removeItems(rowsToRemove);
      }
    }

    /**
     * Bind the events used by the plugin.
     *
     * @private
     */

  }, {
    key: 'registerEvents',
    value: function registerEvents() {
      var _this4 = this;

      this.eventManager.addEventListener(document.documentElement, 'mousemove', function (event) {
        return _this4.onMouseMove(event);
      });
      this.eventManager.addEventListener(document.documentElement, 'mouseup', function () {
        return _this4.onMouseUp();
      });
    }

    /**
     * Unbind the events used by the plugin.
     *
     * @private
     */

  }, {
    key: 'unregisterEvents',
    value: function unregisterEvents() {
      this.eventManager.clear();
    }

    /**
     * `beforeColumnSort` hook callback. If user uses the sorting, manual row moving is disabled.
     *
     * @private
     * @param {Number} column Column index where soring is present
     * @param {*} order State of sorting. ASC/DESC/None
     */

  }, {
    key: 'onBeforeColumnSort',
    value: function onBeforeColumnSort(column, order) {
      var priv = privatePool.get(this);

      priv.disallowMoving = order !== void 0;
    }

    /**
     * Change the behavior of selection / dragging.
     *
     * @private
     * @param {MouseEvent} event
     * @param {CellCoords} coords Visual coordinates.
     * @param {HTMLElement} TD
     * @param {Object} blockCalculations
     */

  }, {
    key: 'onBeforeOnCellMouseDown',
    value: function onBeforeOnCellMouseDown(event, coords, TD, blockCalculations) {
      var wtTable = this.hot.view.wt.wtTable;
      var isHeaderSelection = this.hot.selection.selectedHeader.rows;
      var selection = this.hot.getSelectedRange();
      var priv = privatePool.get(this);

      if (!selection || !isHeaderSelection || priv.pressed || event.button !== 0) {
        priv.pressed = false;
        priv.rowsToMove.length = 0;
        (0, _element.removeClass)(this.hot.rootElement, [CSS_ON_MOVING, CSS_SHOW_UI]);
        return;
      }

      var guidelineIsNotReady = this.guideline.isBuilt() && !this.guideline.isAppended();
      var backlightIsNotReady = this.backlight.isBuilt() && !this.backlight.isAppended();

      if (guidelineIsNotReady && backlightIsNotReady) {
        this.guideline.appendTo(wtTable.hider);
        this.backlight.appendTo(wtTable.hider);
      }

      var from = selection.from,
          to = selection.to;

      var start = Math.min(from.row, to.row);
      var end = Math.max(from.row, to.row);

      if (coords.col < 0 && coords.row >= start && coords.row <= end) {
        blockCalculations.row = true;
        priv.pressed = true;
        priv.target.eventPageY = event.pageY;
        priv.target.coords = coords;
        priv.target.TD = TD;
        priv.rowsToMove = this.prepareRowsToMoving();

        var leftPos = wtTable.holder.scrollLeft + wtTable.getColumnWidth(-1);

        this.backlight.setPosition(null, leftPos);
        this.backlight.setSize(wtTable.hider.offsetWidth - leftPos, this.getRowsHeight(start, end + 1));
        this.backlight.setOffset((this.getRowsHeight(start, coords.row) + event.layerY) * -1, null);

        (0, _element.addClass)(this.hot.rootElement, CSS_ON_MOVING);

        this.refreshPositions();
      } else {
        (0, _element.removeClass)(this.hot.rootElement, CSS_AFTER_SELECTION);
        priv.pressed = false;
        priv.rowsToMove.length = 0;
      }
    }

    /**
     * 'mouseMove' event callback. Fired when pointer move on document.documentElement.
     *
     * @private
     * @param {MouseEvent} event `mousemove` event properties.
     */

  }, {
    key: 'onMouseMove',
    value: function onMouseMove(event) {
      var priv = privatePool.get(this);

      if (!priv.pressed) {
        return;
      }

      // callback for browser which doesn't supports CSS pointer-event: none
      if (event.realTarget === this.backlight.element) {
        var height = this.backlight.getSize().height;
        this.backlight.setSize(null, 0);

        setTimeout(function () {
          this.backlight.setPosition(null, height);
        });
      }

      priv.target.eventPageY = event.pageY;
      this.refreshPositions();
    }

    /**
     * 'beforeOnCellMouseOver' hook callback. Fired when pointer was over cell.
     *
     * @private
     * @param {MouseEvent} event `mouseover` event properties.
     * @param {CellCoords} coords Visual cell coordinates where was fired event.
     * @param {HTMLElement} TD Cell represented as HTMLElement.
     * @param {Object} blockCalculations Object which contains information about blockCalculation for row, column or cells.
     */

  }, {
    key: 'onBeforeOnCellMouseOver',
    value: function onBeforeOnCellMouseOver(event, coords, TD, blockCalculations) {
      var selectedRange = this.hot.getSelectedRange();
      var priv = privatePool.get(this);

      if (!selectedRange || !priv.pressed) {
        return;
      }

      if (priv.rowsToMove.indexOf(coords.row) > -1) {
        (0, _element.removeClass)(this.hot.rootElement, CSS_SHOW_UI);
      } else {
        (0, _element.addClass)(this.hot.rootElement, CSS_SHOW_UI);
      }

      blockCalculations.row = true;
      blockCalculations.column = true;
      blockCalculations.cell = true;
      priv.target.coords = coords;
      priv.target.TD = TD;
    }

    /**
     * `onMouseUp` hook callback.
     *
     * @private
     */

  }, {
    key: 'onMouseUp',
    value: function onMouseUp() {
      var priv = privatePool.get(this);
      var target = priv.target.row;
      var rowsLen = priv.rowsToMove.length;

      priv.pressed = false;
      priv.backlightHeight = 0;

      (0, _element.removeClass)(this.hot.rootElement, [CSS_ON_MOVING, CSS_SHOW_UI, CSS_AFTER_SELECTION]);

      if (this.hot.selection.selectedHeader.rows) {
        (0, _element.addClass)(this.hot.rootElement, CSS_AFTER_SELECTION);
      }

      if (rowsLen < 1 || target === void 0 || priv.rowsToMove.indexOf(target) > -1 || priv.rowsToMove[rowsLen - 1] === target - 1) {
        return;
      }

      this.moveRows(priv.rowsToMove, target);

      this.persistentStateSave();
      this.hot.render();

      if (!priv.disallowMoving) {
        var selectionStart = this.rowsMapper.getIndexByValue(priv.rowsToMove[0]);
        var selectionEnd = this.rowsMapper.getIndexByValue(priv.rowsToMove[rowsLen - 1]);
        this.changeSelection(selectionStart, selectionEnd);
      }

      priv.rowsToMove.length = 0;
    }

    /**
     * `afterScrollHorizontally` hook callback. Fired the table was scrolled horizontally.
     *
     * @private
     */

  }, {
    key: 'onAfterScrollHorizontally',
    value: function onAfterScrollHorizontally() {
      var wtTable = this.hot.view.wt.wtTable;
      var headerWidth = wtTable.getColumnWidth(-1);
      var scrollLeft = wtTable.holder.scrollLeft;
      var posLeft = headerWidth + scrollLeft;

      this.backlight.setPosition(null, posLeft);
      this.backlight.setSize(wtTable.hider.offsetWidth - posLeft);
    }

    /**
     * `afterCreateRow` hook callback.
     *
     * @private
     * @param {Number} index Visual index of the created row.
     * @param {Number} amount Amount of created rows.
     */

  }, {
    key: 'onAfterCreateRow',
    value: function onAfterCreateRow(index, amount) {
      this.rowsMapper.shiftItems(index, amount);
    }

    /**
     * On before remove row listener.
     *
     * @private
     * @param {Number} index Visual row index.
     * @param {Number} amount Defines how many rows removed.
     */

  }, {
    key: 'onBeforeRemoveRow',
    value: function onBeforeRemoveRow(index, amount) {
      var _this5 = this;

      this.removedRows.length = 0;

      if (index !== false) {
        // Collect physical row index.
        (0, _number.rangeEach)(index, index + amount - 1, function (removedIndex) {
          _this5.removedRows.push(_this5.hot.runHooks('modifyRow', removedIndex, _this5.pluginName));
        });
      }
    }

    /**
     * `afterRemoveRow` hook callback.
     *
     * @private
     * @param {Number} index Visual index of the removed row.
     * @param {Number} amount Amount of removed rows.
     */

  }, {
    key: 'onAfterRemoveRow',
    value: function onAfterRemoveRow(index, amount) {
      this.rowsMapper.unshiftItems(this.removedRows);
    }

    /**
     * `afterLoadData` hook callback.
     *
     * @private
     * @param {Boolean} firstTime True if that was loading data during the initialization.
     */

  }, {
    key: 'onAfterLoadData',
    value: function onAfterLoadData(firstTime) {
      this.updateRowsMapper();
    }

    /**
     * 'modifyRow' hook callback.
     *
     * @private
     * @param {Number} row Visual Row index.
     * @returns {Number} Physical row index.
     */

  }, {
    key: 'onModifyRow',
    value: function onModifyRow(row, source) {
      if (source !== this.pluginName) {
        var rowInMapper = this.rowsMapper.getValueByIndex(row);
        row = rowInMapper === null ? row : rowInMapper;
      }

      return row;
    }

    /**
     * 'unmodifyRow' hook callback.
     *
     * @private
     * @param {Number} row Physical row index.
     * @returns {Number} Visual row index.
     */

  }, {
    key: 'onUnmodifyRow',
    value: function onUnmodifyRow(row) {
      var indexInMapper = this.rowsMapper.getIndexByValue(row);

      return indexInMapper === null ? row : indexInMapper;
    }

    /**
     * `afterPluginsInitialized` hook callback.
     *
     * @private
     */

  }, {
    key: 'onAfterPluginsInitialized',
    value: function onAfterPluginsInitialized() {
      this.updateRowsMapper();
      this.initialSettings();
      this.backlight.build();
      this.guideline.build();
    }

    /**
     * Destroy plugin instance.
     */

  }, {
    key: 'destroy',
    value: function destroy() {
      this.backlight.destroy();
      this.guideline.destroy();

      _get(ManualRowMove.prototype.__proto__ || Object.getPrototypeOf(ManualRowMove.prototype), 'destroy', this).call(this);
    }
  }]);

  return ManualRowMove;
}(_base2.default);

(0, _plugins.registerPlugin)('ManualRowMove', ManualRowMove);

exports.default = ManualRowMove;

/***/ }),
/* 369 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


exports.__esModule = true;

var _createClass = 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); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

var _arrayMapper = __webpack_require__(265);

var _arrayMapper2 = _interopRequireDefault(_arrayMapper);

var _array = __webpack_require__(2);

var _object = __webpack_require__(3);

var _number = __webpack_require__(5);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

/**
 * @class RowsMapper
 * @plugin ManualRowMove
 */
var RowsMapper = function () {
  function RowsMapper(manualRowMove) {
    _classCallCheck(this, RowsMapper);

    /**
     * Instance of ManualRowMove plugin.
     *
     * @type {ManualRowMove}
     */
    this.manualRowMove = manualRowMove;
  }

  /**
   * Reset current map array and create new one.
   *
   * @param {Number} [length] Custom generated map length.
   */


  _createClass(RowsMapper, [{
    key: 'createMap',
    value: function createMap(length) {
      var _this = this;

      var originLength = length === void 0 ? this._arrayMap.length : length;

      this._arrayMap.length = 0;

      (0, _number.rangeEach)(originLength - 1, function (itemIndex) {
        _this._arrayMap[itemIndex] = itemIndex;
      });
    }

    /**
     * Destroy class.
     */

  }, {
    key: 'destroy',
    value: function destroy() {
      this._arrayMap = null;
    }

    /**
     * Moving elements in rowsMapper.
     *
     * @param {Number} from Row index to move.
     * @param {Number} to Target index.
     */

  }, {
    key: 'moveRow',
    value: function moveRow(from, to) {
      var indexToMove = this._arrayMap[from];
      this._arrayMap[from] = null;
      this._arrayMap.splice(to, 0, indexToMove);
    }

    /**
     * Clearing arrayMap from `null` entries.
     */

  }, {
    key: 'clearNull',
    value: function clearNull() {
      this._arrayMap = (0, _array.arrayFilter)(this._arrayMap, function (i) {
        return i !== null;
      });
    }
  }]);

  return RowsMapper;
}();

(0, _object.mixin)(RowsMapper, _arrayMapper2.default);

exports.default = RowsMapper;

/***/ }),
/* 370 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


exports.__esModule = true;

var _createClass = 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); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

var _get = function get(object, property, receiver) { if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ("value" in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } };

var _base = __webpack_require__(267);

var _base2 = _interopRequireDefault(_base);

var _element = __webpack_require__(0);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }

function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }

var CSS_CLASSNAME = 'ht__manualRowMove--backlight';

/**
 * @class BacklightUI
 * @util
 */

var BacklightUI = function (_BaseUI) {
  _inherits(BacklightUI, _BaseUI);

  function BacklightUI() {
    _classCallCheck(this, BacklightUI);

    return _possibleConstructorReturn(this, (BacklightUI.__proto__ || Object.getPrototypeOf(BacklightUI)).apply(this, arguments));
  }

  _createClass(BacklightUI, [{
    key: 'build',

    /**
     * Custom className on build process.
     */
    value: function build() {
      _get(BacklightUI.prototype.__proto__ || Object.getPrototypeOf(BacklightUI.prototype), 'build', this).call(this);

      (0, _element.addClass)(this._element, CSS_CLASSNAME);
    }
  }]);

  return BacklightUI;
}(_base2.default);

exports.default = BacklightUI;

/***/ }),
/* 371 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


exports.__esModule = true;

var _createClass = 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); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

var _get = function get(object, property, receiver) { if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ("value" in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } };

var _base = __webpack_require__(267);

var _base2 = _interopRequireDefault(_base);

var _element = __webpack_require__(0);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }

function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }

var CSS_CLASSNAME = 'ht__manualRowMove--guideline';

/**
 * @class GuidelineUI
 * @util
 */

var GuidelineUI = function (_BaseUI) {
  _inherits(GuidelineUI, _BaseUI);

  function GuidelineUI() {
    _classCallCheck(this, GuidelineUI);

    return _possibleConstructorReturn(this, (GuidelineUI.__proto__ || Object.getPrototypeOf(GuidelineUI)).apply(this, arguments));
  }

  _createClass(GuidelineUI, [{
    key: 'build',

    /**
     * Custom className on build process.
     */
    value: function build() {
      _get(GuidelineUI.prototype.__proto__ || Object.getPrototypeOf(GuidelineUI.prototype), 'build', this).call(this);

      (0, _element.addClass)(this._element, CSS_CLASSNAME);
    }
  }]);

  return GuidelineUI;
}(_base2.default);

exports.default = GuidelineUI;

/***/ }),
/* 372 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


exports.__esModule = true;

var _createClass = 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); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

var _get = function get(object, property, receiver) { if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ("value" in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } };

var _base = __webpack_require__(16);

var _base2 = _interopRequireDefault(_base);

var _element = __webpack_require__(0);

var _eventManager = __webpack_require__(4);

var _eventManager2 = _interopRequireDefault(_eventManager);

var _event = __webpack_require__(7);

var _array = __webpack_require__(2);

var _number = __webpack_require__(5);

var _plugins = __webpack_require__(9);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }

function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }

// Developer note! Whenever you make a change in this file, make an analogous change in manualRowResize.js

/**
 * @description
 * ManualRowResize Plugin.
 *
 * Has 2 UI components:
 * - handle - the draggable element that sets the desired height of the row.
 * - guide - the helper guide that shows the desired height as a horizontal guide.
 *
 * @plugin ManualRowResize
 */
var ManualRowResize = function (_BasePlugin) {
  _inherits(ManualRowResize, _BasePlugin);

  function ManualRowResize(hotInstance) {
    _classCallCheck(this, ManualRowResize);

    var _this = _possibleConstructorReturn(this, (ManualRowResize.__proto__ || Object.getPrototypeOf(ManualRowResize)).call(this, hotInstance));

    _this.currentTH = null;
    _this.currentRow = null;
    _this.selectedRows = [];
    _this.currentHeight = null;
    _this.newSize = null;
    _this.startY = null;
    _this.startHeight = null;
    _this.startOffset = null;
    _this.handle = document.createElement('DIV');
    _this.guide = document.createElement('DIV');
    _this.eventManager = new _eventManager2.default(_this);
    _this.pressed = null;
    _this.dblclick = 0;
    _this.autoresizeTimeout = null;
    _this.manualRowHeights = [];

    (0, _element.addClass)(_this.handle, 'manualRowResizer');
    (0, _element.addClass)(_this.guide, 'manualRowResizerGuide');
    return _this;
  }

  /**
   * Check if the plugin is enabled in the handsontable settings.
   *
   * @returns {Boolean}
   */


  _createClass(ManualRowResize, [{
    key: 'isEnabled',
    value: function isEnabled() {
      return this.hot.getSettings().manualRowResize;
    }

    /**
     * Enable plugin for this Handsontable instance.
     */

  }, {
    key: 'enablePlugin',
    value: function enablePlugin() {
      var _this2 = this;

      if (this.enabled) {
        return;
      }

      this.manualRowHeights = [];

      var initialRowHeights = this.hot.getSettings().manualRowResize;
      var loadedManualRowHeights = this.loadManualRowHeights();

      if (typeof loadedManualRowHeights != 'undefined') {
        this.manualRowHeights = loadedManualRowHeights;
      } else if (Array.isArray(initialRowHeights)) {
        this.manualRowHeights = initialRowHeights;
      } else {
        this.manualRowHeights = [];
      }

      this.addHook('modifyRowHeight', function (height, row) {
        return _this2.onModifyRowHeight(height, row);
      });

      // Handsontable.hooks.register('beforeRowResize');
      // Handsontable.hooks.register('afterRowResize');

      this.bindEvents();

      _get(ManualRowResize.prototype.__proto__ || Object.getPrototypeOf(ManualRowResize.prototype), 'enablePlugin', this).call(this);
    }

    /**
     * Updates the plugin to use the latest options you have specified.
     */

  }, {
    key: 'updatePlugin',
    value: function updatePlugin() {
      var initialRowHeights = this.hot.getSettings().manualRowResize;

      if (Array.isArray(initialRowHeights)) {
        this.manualRowHeights = initialRowHeights;
      } else if (!initialRowHeights) {
        this.manualRowHeights = [];
      }
    }

    /**
     * Disable plugin for this Handsontable instance.
     */

  }, {
    key: 'disablePlugin',
    value: function disablePlugin() {
      _get(ManualRowResize.prototype.__proto__ || Object.getPrototypeOf(ManualRowResize.prototype), 'disablePlugin', this).call(this);
    }

    /**
     * Save the current sizes using the persistentState plugin.
     */

  }, {
    key: 'saveManualRowHeights',
    value: function saveManualRowHeights() {
      this.hot.runHooks('persistentStateSave', 'manualRowHeights', this.manualRowHeights);
    }

    /**
     * Load the previously saved sizes using the persistentState plugin.
     *
     * @returns {Array}
     */

  }, {
    key: 'loadManualRowHeights',
    value: function loadManualRowHeights() {
      var storedState = {};

      this.hot.runHooks('persistentStateLoad', 'manualRowHeights', storedState);

      return storedState.value;
    }

    /**
     * Set the resize handle position.
     *
     * @param {HTMLCellElement} TH TH HTML element.
     */

  }, {
    key: 'setupHandlePosition',
    value: function setupHandlePosition(TH) {
      var _this3 = this;

      this.currentTH = TH;
      var row = this.hot.view.wt.wtTable.getCoords(TH).row; // getCoords returns CellCoords
      var headerWidth = (0, _element.outerWidth)(this.currentTH);

      if (row >= 0) {
        // if not col header
        var box = this.currentTH.getBoundingClientRect();

        this.currentRow = row;
        this.selectedRows = [];

        if (this.hot.selection.isSelected() && this.hot.selection.selectedHeader.rows) {
          var _hot$getSelectedRange = this.hot.getSelectedRange(),
              from = _hot$getSelectedRange.from,
              to = _hot$getSelectedRange.to;

          var start = from.row;
          var end = to.row;

          if (start >= end) {
            start = to.row;
            end = from.row;
          }

          if (this.currentRow >= start && this.currentRow <= end) {
            (0, _number.rangeEach)(start, end, function (i) {
              return _this3.selectedRows.push(i);
            });
          } else {
            this.selectedRows.push(this.currentRow);
          }
        } else {
          this.selectedRows.push(this.currentRow);
        }

        this.startOffset = box.top - 6;
        this.startHeight = parseInt(box.height, 10);
        this.handle.style.left = box.left + 'px';
        this.handle.style.top = this.startOffset + this.startHeight + 'px';
        this.handle.style.width = headerWidth + 'px';
        this.hot.rootElement.appendChild(this.handle);
      }
    }

    /**
     * Refresh the resize handle position.
     */

  }, {
    key: 'refreshHandlePosition',
    value: function refreshHandlePosition() {
      this.handle.style.top = this.startOffset + this.currentHeight + 'px';
    }

    /**
     * Set the resize guide position.
     */

  }, {
    key: 'setupGuidePosition',
    value: function setupGuidePosition() {
      var handleWidth = parseInt((0, _element.outerWidth)(this.handle), 10);
      var handleRightPosition = parseInt(this.handle.style.left, 10) + handleWidth;
      var maximumVisibleElementWidth = parseInt(this.hot.view.maximumVisibleElementWidth(0), 10);
      (0, _element.addClass)(this.handle, 'active');
      (0, _element.addClass)(this.guide, 'active');

      this.guide.style.top = this.handle.style.top;
      this.guide.style.left = handleRightPosition + 'px';
      this.guide.style.width = maximumVisibleElementWidth - handleWidth + 'px';
      this.hot.rootElement.appendChild(this.guide);
    }

    /**
     * Refresh the resize guide position.
     */

  }, {
    key: 'refreshGuidePosition',
    value: function refreshGuidePosition() {
      this.guide.style.top = this.handle.style.top;
    }

    /**
     * Hide both the resize handle and resize guide.
     */

  }, {
    key: 'hideHandleAndGuide',
    value: function hideHandleAndGuide() {
      (0, _element.removeClass)(this.handle, 'active');
      (0, _element.removeClass)(this.guide, 'active');
    }

    /**
     * Check if provided element is considered as a row header.
     *
     * @param {HTMLElement} element HTML element.
     * @returns {Boolean}
     */

  }, {
    key: 'checkIfRowHeader',
    value: function checkIfRowHeader(element) {
      if (element != this.hot.rootElement) {
        var parent = element.parentNode;

        if (parent.tagName === 'TBODY') {
          return true;
        }

        return this.checkIfRowHeader(parent);
      }

      return false;
    }

    /**
     * Get the TH element from the provided element.
     *
     * @param {HTMLElement} element HTML element.
     * @returns {HTMLElement}
     */

  }, {
    key: 'getTHFromTargetElement',
    value: function getTHFromTargetElement(element) {
      if (element.tagName != 'TABLE') {
        if (element.tagName == 'TH') {
          return element;
        }
        return this.getTHFromTargetElement(element.parentNode);
      }

      return null;
    }

    /**
     * 'mouseover' event callback - set the handle position.
     *
     * @private
     * @param {MouseEvent} event
     */

  }, {
    key: 'onMouseOver',
    value: function onMouseOver(event) {
      if (this.checkIfRowHeader(event.target)) {
        var th = this.getTHFromTargetElement(event.target);

        if (th) {
          if (!this.pressed) {
            this.setupHandlePosition(th);
          }
        }
      }
    }

    /**
     * Auto-size row after doubleclick - callback.
     *
     * @private
     */

  }, {
    key: 'afterMouseDownTimeout',
    value: function afterMouseDownTimeout() {
      var _this4 = this;

      var render = function render() {
        _this4.hot.forceFullRender = true;
        _this4.hot.view.render(); // updates all
        _this4.hot.view.wt.wtOverlays.adjustElementsSize(true);
      };
      var resize = function resize(selectedRow, forceRender) {
        var hookNewSize = _this4.hot.runHooks('beforeRowResize', selectedRow, _this4.newSize, true);

        if (hookNewSize !== void 0) {
          _this4.newSize = hookNewSize;
        }

        _this4.setManualSize(selectedRow, _this4.newSize); // double click sets auto row size

        if (forceRender) {
          render();
        }

        _this4.hot.runHooks('afterRowResize', selectedRow, _this4.newSize, true);
      };

      if (this.dblclick >= 2) {
        var selectedRowsLength = this.selectedRows.length;

        if (selectedRowsLength > 1) {
          (0, _array.arrayEach)(this.selectedRows, function (selectedRow) {
            resize(selectedRow);
          });
          render();
        } else {
          (0, _array.arrayEach)(this.selectedRows, function (selectedRow) {
            resize(selectedRow, true);
          });
        }
      }
      this.dblclick = 0;
      this.autoresizeTimeout = null;
    }

    /**
     * 'mousedown' event callback.
     *
     * @private
     * @param {MouseEvent} event
     */

  }, {
    key: 'onMouseDown',
    value: function onMouseDown(event) {
      var _this5 = this;

      if ((0, _element.hasClass)(event.target, 'manualRowResizer')) {
        this.setupGuidePosition();
        this.pressed = this.hot;

        if (this.autoresizeTimeout == null) {
          this.autoresizeTimeout = setTimeout(function () {
            return _this5.afterMouseDownTimeout();
          }, 500);

          this.hot._registerTimeout(this.autoresizeTimeout);
        }
        this.dblclick++;

        this.startY = (0, _event.pageY)(event);
        this.newSize = this.startHeight;
      }
    }

    /**
     * 'mousemove' event callback - refresh the handle and guide positions, cache the new row height.
     *
     * @private
     * @param {MouseEvent} event
     */

  }, {
    key: 'onMouseMove',
    value: function onMouseMove(event) {
      var _this6 = this;

      if (this.pressed) {
        this.currentHeight = this.startHeight + ((0, _event.pageY)(event) - this.startY);

        (0, _array.arrayEach)(this.selectedRows, function (selectedRow) {
          _this6.newSize = _this6.setManualSize(selectedRow, _this6.currentHeight);
        });

        this.refreshHandlePosition();
        this.refreshGuidePosition();
      }
    }

    /**
     * 'mouseup' event callback - apply the row resizing.
     *
     * @private
     * @param {MouseEvent} event
     */

  }, {
    key: 'onMouseUp',
    value: function onMouseUp(event) {
      var _this7 = this;

      var render = function render() {
        _this7.hot.forceFullRender = true;
        _this7.hot.view.render(); // updates all
        _this7.hot.view.wt.wtOverlays.adjustElementsSize(true);
      };
      var runHooks = function runHooks(selectedRow, forceRender) {
        _this7.hot.runHooks('beforeRowResize', selectedRow, _this7.newSize);

        if (forceRender) {
          render();
        }

        _this7.saveManualRowHeights();

        _this7.hot.runHooks('afterRowResize', selectedRow, _this7.newSize);
      };
      if (this.pressed) {
        this.hideHandleAndGuide();
        this.pressed = false;

        if (this.newSize != this.startHeight) {
          var selectedRowsLength = this.selectedRows.length;

          if (selectedRowsLength > 1) {
            (0, _array.arrayEach)(this.selectedRows, function (selectedRow) {
              runHooks(selectedRow);
            });
            render();
          } else {
            (0, _array.arrayEach)(this.selectedRows, function (selectedRow) {
              runHooks(selectedRow, true);
            });
          }
        }

        this.setupHandlePosition(this.currentTH);
      }
    }

    /**
     * Bind the mouse events.
     *
     * @private
     */

  }, {
    key: 'bindEvents',
    value: function bindEvents() {
      var _this8 = this;

      this.eventManager.addEventListener(this.hot.rootElement, 'mouseover', function (e) {
        return _this8.onMouseOver(e);
      });
      this.eventManager.addEventListener(this.hot.rootElement, 'mousedown', function (e) {
        return _this8.onMouseDown(e);
      });
      this.eventManager.addEventListener(window, 'mousemove', function (e) {
        return _this8.onMouseMove(e);
      });
      this.eventManager.addEventListener(window, 'mouseup', function (e) {
        return _this8.onMouseUp(e);
      });
    }

    /**
     * Cache the current row height.
     *
     * @param {Number} row Visual row index.
     * @param {Number} height Row height.
     * @returns {Number}
     */

  }, {
    key: 'setManualSize',
    value: function setManualSize(row, height) {
      row = this.hot.runHooks('modifyRow', row);
      this.manualRowHeights[row] = height;

      return height;
    }

    /**
     * Modify the provided row height, based on the plugin settings.
     *
     * @private
     * @param {Number} height Row height.
     * @param {Number} row Visual row index.
     * @returns {Number}
     */

  }, {
    key: 'onModifyRowHeight',
    value: function onModifyRowHeight(height, row) {
      if (this.enabled) {
        var autoRowSizePlugin = this.hot.getPlugin('autoRowSize');
        var autoRowHeightResult = autoRowSizePlugin ? autoRowSizePlugin.heights[row] : null;

        row = this.hot.runHooks('modifyRow', row);

        var manualRowHeight = this.manualRowHeights[row];

        if (manualRowHeight !== void 0 && (manualRowHeight === autoRowHeightResult || manualRowHeight > (height || 0))) {
          return manualRowHeight;
        }
      }

      return height;
    }
  }]);

  return ManualRowResize;
}(_base2.default);

(0, _plugins.registerPlugin)('manualRowResize', ManualRowResize);

exports.default = ManualRowResize;

/***/ }),
/* 373 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


exports.__esModule = true;

var _pluginHooks = __webpack_require__(11);

var _pluginHooks2 = _interopRequireDefault(_pluginHooks);

var _plugins = __webpack_require__(9);

var _event = __webpack_require__(7);

var _src = __webpack_require__(14);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

function CellInfoCollection() {
  var collection = [];

  collection.getInfo = function (row, col) {
    for (var i = 0, ilen = this.length; i < ilen; i++) {
      if (this[i].row <= row && this[i].row + this[i].rowspan - 1 >= row && this[i].col <= col && this[i].col + this[i].colspan - 1 >= col) {
        return this[i];
      }
    }
  };

  collection.setInfo = function (info) {
    for (var i = 0, ilen = this.length; i < ilen; i++) {
      if (this[i].row === info.row && this[i].col === info.col) {
        this[i] = info;
        return;
      }
    }
    this.push(info);
  };

  collection.removeInfo = function (row, col) {
    for (var i = 0, ilen = this.length; i < ilen; i++) {
      if (this[i].row === row && this[i].col === col) {
        this.splice(i, 1);
        break;
      }
    }
  };

  return collection;
}

/**
 * Plugin used to merge cells in Handsontable.
 *
 * @private
 * @plugin MergeCells
 * @class MergeCells
 */
function MergeCells(mergeCellsSetting) {
  this.mergedCellInfoCollection = new CellInfoCollection();

  if (Array.isArray(mergeCellsSetting)) {
    for (var i = 0, ilen = mergeCellsSetting.length; i < ilen; i++) {
      this.mergedCellInfoCollection.setInfo(mergeCellsSetting[i]);
    }
  }
}

/**
 * @param cellRange (CellRange)
 */
MergeCells.prototype.canMergeRange = function (cellRange) {
  // is more than one cell selected
  return !cellRange.isSingle();
};

MergeCells.prototype.mergeRange = function (cellRange) {
  if (!this.canMergeRange(cellRange)) {
    return;
  }

  // normalize top left corner
  var topLeft = cellRange.getTopLeftCorner();
  var bottomRight = cellRange.getBottomRightCorner();

  var mergeParent = {};
  mergeParent.row = topLeft.row;
  mergeParent.col = topLeft.col;
  // TD has rowspan == 1 by default. rowspan == 2 means spread over 2 cells
  mergeParent.rowspan = bottomRight.row - topLeft.row + 1;
  mergeParent.colspan = bottomRight.col - topLeft.col + 1;
  this.mergedCellInfoCollection.setInfo(mergeParent);
};

MergeCells.prototype.mergeOrUnmergeSelection = function (cellRange) {
  var info = this.mergedCellInfoCollection.getInfo(cellRange.from.row, cellRange.from.col);
  if (info) {
    // unmerge
    this.unmergeSelection(cellRange.from);
  } else {
    // merge
    this.mergeSelection(cellRange);
  }
};

MergeCells.prototype.mergeSelection = function (cellRange) {
  this.mergeRange(cellRange);
};

MergeCells.prototype.unmergeSelection = function (cellRange) {
  var info = this.mergedCellInfoCollection.getInfo(cellRange.row, cellRange.col);
  this.mergedCellInfoCollection.removeInfo(info.row, info.col);
};

MergeCells.prototype.applySpanProperties = function (TD, row, col) {
  var info = this.mergedCellInfoCollection.getInfo(row, col);

  if (info) {
    if (info.row === row && info.col === col) {
      TD.setAttribute('rowspan', info.rowspan);
      TD.setAttribute('colspan', info.colspan);
    } else {
      TD.removeAttribute('rowspan');
      TD.removeAttribute('colspan');

      TD.style.display = 'none';
    }
  } else {
    TD.removeAttribute('rowspan');
    TD.removeAttribute('colspan');
  }
};

MergeCells.prototype.modifyTransform = function (hook, currentSelectedRange, delta) {
  var sameRowspan = function sameRowspan(merged, coords) {
    if (coords.row >= merged.row && coords.row <= merged.row + merged.rowspan - 1) {
      return true;
    }
    return false;
  },
      sameColspan = function sameColspan(merged, coords) {
    if (coords.col >= merged.col && coords.col <= merged.col + merged.colspan - 1) {
      return true;
    }
    return false;
  },
      getNextPosition = function getNextPosition(newDelta) {
    return new _src.CellCoords(currentSelectedRange.to.row + newDelta.row, currentSelectedRange.to.col + newDelta.col);
  };

  var newDelta = {
    row: delta.row,
    col: delta.col
  };

  if (hook == 'modifyTransformStart') {
    /* eslint-disable block-scoped-var */
    var nextPosition;

    if (!this.lastDesiredCoords) {
      this.lastDesiredCoords = new _src.CellCoords(null, null);
    }
    var currentPosition = new _src.CellCoords(currentSelectedRange.highlight.row, currentSelectedRange.highlight.col),

    // if current position's parent is a merged range, returns it
    mergedParent = this.mergedCellInfoCollection.getInfo(currentPosition.row, currentPosition.col),
        currentRangeContainsMerge; // if current range contains a merged range

    for (var i = 0, mergesLength = this.mergedCellInfoCollection.length; i < mergesLength; i++) {
      var range = this.mergedCellInfoCollection[i];
      range = new _src.CellCoords(range.row + range.rowspan - 1, range.col + range.colspan - 1);
      if (currentSelectedRange.includes(range)) {
        currentRangeContainsMerge = true;
        break;
      }
    }

    if (mergedParent) {
      // only merge selected
      var mergeTopLeft = new _src.CellCoords(mergedParent.row, mergedParent.col);
      var mergeBottomRight = new _src.CellCoords(mergedParent.row + mergedParent.rowspan - 1, mergedParent.col + mergedParent.colspan - 1);
      var mergeRange = new _src.CellRange(mergeTopLeft, mergeTopLeft, mergeBottomRight);

      if (!mergeRange.includes(this.lastDesiredCoords)) {
        this.lastDesiredCoords = new _src.CellCoords(null, null); // reset outdated version of lastDesiredCoords
      }

      newDelta.row = this.lastDesiredCoords.row ? this.lastDesiredCoords.row - currentPosition.row : newDelta.row;
      newDelta.col = this.lastDesiredCoords.col ? this.lastDesiredCoords.col - currentPosition.col : newDelta.col;

      if (delta.row > 0) {
        // moving down
        newDelta.row = mergedParent.row + mergedParent.rowspan - 1 - currentPosition.row + delta.row;
      } else if (delta.row < 0) {
        // moving up
        newDelta.row = currentPosition.row - mergedParent.row + delta.row;
      }
      if (delta.col > 0) {
        // moving right
        newDelta.col = mergedParent.col + mergedParent.colspan - 1 - currentPosition.col + delta.col;
      } else if (delta.col < 0) {
        // moving left
        newDelta.col = currentPosition.col - mergedParent.col + delta.col;
      }
    }

    nextPosition = new _src.CellCoords(currentSelectedRange.highlight.row + newDelta.row, currentSelectedRange.highlight.col + newDelta.col);

    var nextParentIsMerged = this.mergedCellInfoCollection.getInfo(nextPosition.row, nextPosition.col);

    if (nextParentIsMerged) {
      // skipping the invisible cells in the merge range
      this.lastDesiredCoords = nextPosition;
      newDelta = {
        row: nextParentIsMerged.row - currentPosition.row,
        col: nextParentIsMerged.col - currentPosition.col
      };
    }
  } else if (hook == 'modifyTransformEnd') {
    for (var _i = 0, _mergesLength = this.mergedCellInfoCollection.length; _i < _mergesLength; _i++) {
      var currentMerge = this.mergedCellInfoCollection[_i];
      var _mergeTopLeft = new _src.CellCoords(currentMerge.row, currentMerge.col);
      var _mergeBottomRight = new _src.CellCoords(currentMerge.row + currentMerge.rowspan - 1, currentMerge.col + currentMerge.colspan - 1);
      var mergedRange = new _src.CellRange(_mergeTopLeft, _mergeTopLeft, _mergeBottomRight);
      var sharedBorders = currentSelectedRange.getBordersSharedWith(mergedRange);

      if (mergedRange.isEqual(currentSelectedRange)) {
        // only the merged range is selected
        currentSelectedRange.setDirection('NW-SE');
      } else if (sharedBorders.length > 0) {
        var mergeHighlighted = currentSelectedRange.highlight.isEqual(mergedRange.from);

        if (sharedBorders.indexOf('top') > -1) {
          // if range shares a border with the merged section, change range direction accordingly
          if (currentSelectedRange.to.isSouthEastOf(mergedRange.from) && mergeHighlighted) {
            currentSelectedRange.setDirection('NW-SE');
          } else if (currentSelectedRange.to.isSouthWestOf(mergedRange.from) && mergeHighlighted) {
            currentSelectedRange.setDirection('NE-SW');
          }
        } else if (sharedBorders.indexOf('bottom') > -1) {
          if (currentSelectedRange.to.isNorthEastOf(mergedRange.from) && mergeHighlighted) {
            currentSelectedRange.setDirection('SW-NE');
          } else if (currentSelectedRange.to.isNorthWestOf(mergedRange.from) && mergeHighlighted) {
            currentSelectedRange.setDirection('SE-NW');
          }
        }
      }

      nextPosition = getNextPosition(newDelta);
      var withinRowspan = sameRowspan(currentMerge, nextPosition),
          withinColspan = sameColspan(currentMerge, nextPosition);

      if (currentSelectedRange.includesRange(mergedRange) && (mergedRange.includes(nextPosition) || withinRowspan || withinColspan)) {
        // if next step overlaps a merged range, jump past it
        if (withinRowspan) {
          if (newDelta.row < 0) {
            newDelta.row -= currentMerge.rowspan - 1;
          } else if (newDelta.row > 0) {
            newDelta.row += currentMerge.rowspan - 1;
          }
        }
        if (withinColspan) {
          if (newDelta.col < 0) {
            newDelta.col -= currentMerge.colspan - 1;
          } else if (newDelta.col > 0) {
            newDelta.col += currentMerge.colspan - 1;
          }
        }
      }
    }
  }

  if (newDelta.row !== 0) {
    delta.row = newDelta.row;
  }
  if (newDelta.col !== 0) {
    delta.col = newDelta.col;
  }
};

MergeCells.prototype.shiftCollection = function (direction, index, count) {
  var shiftVector = [0, 0];

  switch (direction) {
    case 'right':
      shiftVector[0] += 1;

      break;
    case 'left':
      shiftVector[0] -= 1;

      break;
    case 'down':
      shiftVector[1] += 1;

      break;
    case 'up':
      shiftVector[1] -= 1;

      break;
    default:
      break;
  }

  for (var i = 0; i < this.mergedCellInfoCollection.length; i++) {
    var currentMerge = this.mergedCellInfoCollection[i];

    if (direction === 'right' || direction === 'left') {
      if (index <= currentMerge.col) {
        currentMerge.col += shiftVector[0];
      }
    } else if (index <= currentMerge.row) {
      currentMerge.row += shiftVector[1];
    }
  }
};

var beforeInit = function beforeInit() {
  var instance = this;
  var mergeCellsSetting = instance.getSettings().mergeCells;

  if (mergeCellsSetting) {
    if (!instance.mergeCells) {
      instance.mergeCells = new MergeCells(mergeCellsSetting);
    }
  }
};

var afterInit = function afterInit() {
  var instance = this;
  if (instance.mergeCells) {
    /**
     * Monkey patch Table.prototype.getCell to return TD for merged cell parent if asked for TD of a cell that is
     * invisible due to the merge. This is not the cleanest solution but there is a test case for it (merged cells scroll) so feel free to refactor it!
     */
    instance.view.wt.wtTable.getCell = function (coords) {
      if (instance.getSettings().mergeCells) {
        var mergeParent = instance.mergeCells.mergedCellInfoCollection.getInfo(coords.row, coords.col);
        if (mergeParent) {
          coords = mergeParent;
        }
      }
      return _src.Table.prototype.getCell.call(this, coords);
    };
  }
};

var afterUpdateSettings = function afterUpdateSettings() {
  var instance = this;
  var mergeCellsSetting = instance.getSettings().mergeCells;

  if (mergeCellsSetting) {
    if (instance.mergeCells) {
      instance.mergeCells.mergedCellInfoCollection = new CellInfoCollection();

      if (Array.isArray(mergeCellsSetting)) {
        for (var i = 0, ilen = mergeCellsSetting.length; i < ilen; i++) {
          instance.mergeCells.mergedCellInfoCollection.setInfo(mergeCellsSetting[i]);
        }
      }
    } else {
      instance.mergeCells = new MergeCells(mergeCellsSetting);
    }
  } else if (instance.mergeCells) {
    // it doesn't actually turn off the plugin, just resets the settings. Need to refactor.
    instance.mergeCells.mergedCellInfoCollection = new CellInfoCollection();
  }
};

var onBeforeKeyDown = function onBeforeKeyDown(event) {
  if (!this.mergeCells) {
    return;
  }

  var ctrlDown = (event.ctrlKey || event.metaKey) && !event.altKey;

  if (ctrlDown) {
    if (event.keyCode === 77) {
      // CTRL + M
      this.mergeCells.mergeOrUnmergeSelection(this.getSelectedRange());
      this.render();
      (0, _event.stopImmediatePropagation)(event);
    }
  }
};

var addMergeActionsToContextMenu = function addMergeActionsToContextMenu(defaultOptions) {
  if (!this.getSettings().mergeCells) {
    return;
  }

  defaultOptions.items.push({ name: '---------' });
  defaultOptions.items.push({
    key: 'mergeCells',
    name: function name() {
      var sel = this.getSelected();
      var info = this.mergeCells.mergedCellInfoCollection.getInfo(sel[0], sel[1]);
      if (info) {
        return 'Unmerge cells';
      }
      return 'Merge cells';
    },
    callback: function callback() {
      this.mergeCells.mergeOrUnmergeSelection(this.getSelectedRange());
      this.render();
    },
    disabled: function disabled() {
      return this.selection.selectedHeader.corner;
    }
  });
};

var afterRenderer = function afterRenderer(TD, row, col, prop, value, cellProperties) {
  if (this.mergeCells) {
    this.mergeCells.applySpanProperties(TD, row, col);
  }
};

var modifyTransformFactory = function modifyTransformFactory(hook) {
  return function (delta) {
    var mergeCellsSetting = this.getSettings().mergeCells;
    if (mergeCellsSetting) {
      var currentSelectedRange = this.getSelectedRange();
      this.mergeCells.modifyTransform(hook, currentSelectedRange, delta);

      if (hook === 'modifyTransformEnd') {
        // sanitize "from" (core.js will sanitize to)
        var totalRows = this.countRows();
        var totalCols = this.countCols();
        if (currentSelectedRange.from.row < 0) {
          currentSelectedRange.from.row = 0;
        } else if (currentSelectedRange.from.row > 0 && currentSelectedRange.from.row >= totalRows) {
          currentSelectedRange.from.row = currentSelectedRange.from - 1;
        }

        if (currentSelectedRange.from.col < 0) {
          currentSelectedRange.from.col = 0;
        } else if (currentSelectedRange.from.col > 0 && currentSelectedRange.from.col >= totalCols) {
          currentSelectedRange.from.col = totalCols - 1;
        }
      }
    }
  };
};

/**
 * While selecting cells with keyboard or mouse, make sure that rectangular area is expanded to the extent of the merged cell
 * @param coords
 */
var beforeSetRangeEnd = function beforeSetRangeEnd(coords) {

  this.lastDesiredCoords = null; // unset lastDesiredCoords when selection is changed with mouse
  var mergeCellsSetting = this.getSettings().mergeCells;
  if (mergeCellsSetting) {
    var selRange = this.getSelectedRange();
    selRange.highlight = new _src.CellCoords(selRange.highlight.row, selRange.highlight.col); // clone in case we will modify its reference
    selRange.to = coords;

    var rangeExpanded = false;
    do {
      rangeExpanded = false;

      for (var i = 0, ilen = this.mergeCells.mergedCellInfoCollection.length; i < ilen; i++) {
        var cellInfo = this.mergeCells.mergedCellInfoCollection[i];
        var mergedCellTopLeft = new _src.CellCoords(cellInfo.row, cellInfo.col);
        var mergedCellBottomRight = new _src.CellCoords(cellInfo.row + cellInfo.rowspan - 1, cellInfo.col + cellInfo.colspan - 1);

        var mergedCellRange = new _src.CellRange(mergedCellTopLeft, mergedCellTopLeft, mergedCellBottomRight);
        if (selRange.expandByRange(mergedCellRange)) {
          coords.row = selRange.to.row;
          coords.col = selRange.to.col;

          rangeExpanded = true;
        }
      }
    } while (rangeExpanded);
  }
};

/**
 * Returns correct coordinates for merged start / end cells in selection for area borders
 * @param corners
 * @param className
 */
var beforeDrawAreaBorders = function beforeDrawAreaBorders(corners, className) {
  if (className && className == 'area') {
    var mergeCellsSetting = this.getSettings().mergeCells;
    if (mergeCellsSetting) {
      var selRange = this.getSelectedRange();
      var startRange = new _src.CellRange(selRange.from, selRange.from, selRange.from);
      var stopRange = new _src.CellRange(selRange.to, selRange.to, selRange.to);

      for (var i = 0, ilen = this.mergeCells.mergedCellInfoCollection.length; i < ilen; i++) {
        var cellInfo = this.mergeCells.mergedCellInfoCollection[i];
        var mergedCellTopLeft = new _src.CellCoords(cellInfo.row, cellInfo.col);
        var mergedCellBottomRight = new _src.CellCoords(cellInfo.row + cellInfo.rowspan - 1, cellInfo.col + cellInfo.colspan - 1);
        var mergedCellRange = new _src.CellRange(mergedCellTopLeft, mergedCellTopLeft, mergedCellBottomRight);

        if (startRange.expandByRange(mergedCellRange)) {
          corners[0] = startRange.from.row;
          corners[1] = startRange.from.col;
        }

        if (stopRange.expandByRange(mergedCellRange)) {
          corners[2] = stopRange.from.row;
          corners[3] = stopRange.from.col;
        }
      }
    }
  }
};

var afterGetCellMeta = function afterGetCellMeta(row, col, cellProperties) {
  var mergeCellsSetting = this.getSettings().mergeCells;
  if (mergeCellsSetting) {
    var mergeParent = this.mergeCells.mergedCellInfoCollection.getInfo(row, col);
    if (mergeParent && (mergeParent.row != row || mergeParent.col != col)) {
      cellProperties.copyable = false;
    }
  }
};

var afterViewportRowCalculatorOverride = function afterViewportRowCalculatorOverride(calc) {
  var mergeCellsSetting = this.getSettings().mergeCells;
  if (mergeCellsSetting) {
    var colCount = this.countCols();
    var mergeParent;
    for (var c = 0; c < colCount; c++) {
      mergeParent = this.mergeCells.mergedCellInfoCollection.getInfo(calc.startRow, c);
      if (mergeParent) {
        if (mergeParent.row < calc.startRow) {
          calc.startRow = mergeParent.row;
          return afterViewportRowCalculatorOverride.call(this, calc); // recursively search upwards
        }
      }
      mergeParent = this.mergeCells.mergedCellInfoCollection.getInfo(calc.endRow, c);
      if (mergeParent) {
        var mergeEnd = mergeParent.row + mergeParent.rowspan - 1;
        if (mergeEnd > calc.endRow) {
          calc.endRow = mergeEnd;
          return afterViewportRowCalculatorOverride.call(this, calc); // recursively search upwards
        }
      }
    }
  }
};

var afterViewportColumnCalculatorOverride = function afterViewportColumnCalculatorOverride(calc) {
  var mergeCellsSetting = this.getSettings().mergeCells;
  if (mergeCellsSetting) {
    var rowCount = this.countRows();
    var mergeParent;
    for (var r = 0; r < rowCount; r++) {
      mergeParent = this.mergeCells.mergedCellInfoCollection.getInfo(r, calc.startColumn);

      if (mergeParent) {
        if (mergeParent.col < calc.startColumn) {
          calc.startColumn = mergeParent.col;
          return afterViewportColumnCalculatorOverride.call(this, calc); // recursively search upwards
        }
      }
      mergeParent = this.mergeCells.mergedCellInfoCollection.getInfo(r, calc.endColumn);
      if (mergeParent) {
        var mergeEnd = mergeParent.col + mergeParent.colspan - 1;
        if (mergeEnd > calc.endColumn) {
          calc.endColumn = mergeEnd;
          return afterViewportColumnCalculatorOverride.call(this, calc); // recursively search upwards
        }
      }
    }
  }
};

var isMultipleSelection = function isMultipleSelection(isMultiple) {
  if (isMultiple && this.mergeCells) {
    var mergedCells = this.mergeCells.mergedCellInfoCollection,
        selectionRange = this.getSelectedRange();

    for (var group in mergedCells) {
      if (selectionRange.highlight.row == mergedCells[group].row && selectionRange.highlight.col == mergedCells[group].col && selectionRange.to.row == mergedCells[group].row + mergedCells[group].rowspan - 1 && selectionRange.to.col == mergedCells[group].col + mergedCells[group].colspan - 1) {
        return false;
      }
    }
  }
  return isMultiple;
};

function modifyAutofillRange(select, drag) {
  var mergeCellsSetting = this.getSettings().mergeCells;

  if (!mergeCellsSetting || this.selection.isMultiple()) {
    return;
  }
  var info = this.mergeCells.mergedCellInfoCollection.getInfo(select[0], select[1]);

  if (info) {
    select[0] = info.row;
    select[1] = info.col;
    select[2] = info.row + info.rowspan - 1;
    select[3] = info.col + info.colspan - 1;
  }
}

function onAfterCreateCol(col, count) {
  if (this.mergeCells) {
    this.mergeCells.shiftCollection('right', col, count);
  }
}

function onAfterRemoveCol(col, count) {
  if (this.mergeCells) {
    this.mergeCells.shiftCollection('left', col, count);
  }
}

function onAfterCreateRow(row, count) {
  if (this.mergeCells) {
    this.mergeCells.shiftCollection('down', row, count);
  }
}

function onAfterRemoveRow(row, count) {
  if (this.mergeCells) {
    this.mergeCells.shiftCollection('up', row, count);
  }
}

var hook = _pluginHooks2.default.getSingleton();

hook.add('beforeInit', beforeInit);
hook.add('afterInit', afterInit);
hook.add('afterUpdateSettings', afterUpdateSettings);
hook.add('beforeKeyDown', onBeforeKeyDown);
hook.add('modifyTransformStart', modifyTransformFactory('modifyTransformStart'));
hook.add('modifyTransformEnd', modifyTransformFactory('modifyTransformEnd'));
hook.add('beforeSetRangeEnd', beforeSetRangeEnd);
hook.add('beforeDrawBorders', beforeDrawAreaBorders);
hook.add('afterIsMultipleSelection', isMultipleSelection);
hook.add('afterRenderer', afterRenderer);
hook.add('afterContextMenuDefaultOptions', addMergeActionsToContextMenu);
hook.add('afterGetCellMeta', afterGetCellMeta);
hook.add('afterViewportRowCalculatorOverride', afterViewportRowCalculatorOverride);
hook.add('afterViewportColumnCalculatorOverride', afterViewportColumnCalculatorOverride);
hook.add('modifyAutofillRange', modifyAutofillRange);
hook.add('afterCreateCol', onAfterCreateCol);
hook.add('afterRemoveCol', onAfterRemoveCol);
hook.add('afterCreateRow', onAfterCreateRow);
hook.add('afterRemoveRow', onAfterRemoveRow);

exports.default = MergeCells;

/***/ }),
/* 374 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


exports.__esModule = true;

var _createClass = 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); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

var _get = function get(object, property, receiver) { if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ("value" in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } };

var _pluginHooks = __webpack_require__(11);

var _pluginHooks2 = _interopRequireDefault(_pluginHooks);

var _element = __webpack_require__(0);

var _browser = __webpack_require__(22);

var _base = __webpack_require__(16);

var _base2 = _interopRequireDefault(_base);

var _eventManager = __webpack_require__(4);

var _eventManager2 = _interopRequireDefault(_eventManager);

var _plugins = __webpack_require__(9);

var _src = __webpack_require__(14);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }

function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }

/**
 * @private
 * @plugin MultipleSelectionHandles
 */
var MultipleSelectionHandles = function (_BasePlugin) {
  _inherits(MultipleSelectionHandles, _BasePlugin);

  /**
   * @param {Object} hotInstance
   */
  function MultipleSelectionHandles(hotInstance) {
    _classCallCheck(this, MultipleSelectionHandles);

    /**
     * @type {Array}
     */
    var _this2 = _possibleConstructorReturn(this, (MultipleSelectionHandles.__proto__ || Object.getPrototypeOf(MultipleSelectionHandles)).call(this, hotInstance));

    _this2.dragged = [];
    /**
     * Instance of EventManager.
     *
     * @type {EventManager}
     */
    _this2.eventManager = null;
    /**
     * @type {null}
     */
    _this2.lastSetCell = null;
    return _this2;
  }

  /**
   * Check if the plugin is enabled in the handsontable settings.
   *
   * @returns {Boolean}
   */


  _createClass(MultipleSelectionHandles, [{
    key: 'isEnabled',
    value: function isEnabled() {
      return (0, _browser.isMobileBrowser)();
    }

    /**
     * Enable plugin for this Handsontable instance.
     */

  }, {
    key: 'enablePlugin',
    value: function enablePlugin() {
      if (this.enabled) {
        return;
      }
      if (!this.eventManager) {
        this.eventManager = new _eventManager2.default(this);
      }
      this.registerListeners();
      _get(MultipleSelectionHandles.prototype.__proto__ || Object.getPrototypeOf(MultipleSelectionHandles.prototype), 'enablePlugin', this).call(this);
    }

    /**
     * Bind the touch events
     * @private
     */

  }, {
    key: 'registerListeners',
    value: function registerListeners() {
      var _this = this;

      function removeFromDragged(query) {

        if (_this.dragged.length === 1) {
          // clear array
          _this.dragged.splice(0, _this.dragged.length);

          return true;
        }

        var entryPosition = _this.dragged.indexOf(query);

        if (entryPosition == -1) {
          return false;
        } else if (entryPosition === 0) {
          _this.dragged = _this.dragged.slice(0, 1);
        } else if (entryPosition == 1) {
          _this.dragged = _this.dragged.slice(-1);
        }
      }

      this.eventManager.addEventListener(this.hot.rootElement, 'touchstart', function (event) {
        var selectedRange = void 0;

        if ((0, _element.hasClass)(event.target, 'topLeftSelectionHandle-HitArea')) {
          selectedRange = _this.hot.getSelectedRange();

          _this.dragged.push('topLeft');

          _this.touchStartRange = {
            width: selectedRange.getWidth(),
            height: selectedRange.getHeight(),
            direction: selectedRange.getDirection()
          };

          event.preventDefault();
          return false;
        } else if ((0, _element.hasClass)(event.target, 'bottomRightSelectionHandle-HitArea')) {
          selectedRange = _this.hot.getSelectedRange();

          _this.dragged.push('bottomRight');

          _this.touchStartRange = {
            width: selectedRange.getWidth(),
            height: selectedRange.getHeight(),
            direction: selectedRange.getDirection()
          };

          event.preventDefault();
          return false;
        }
      });

      this.eventManager.addEventListener(this.hot.rootElement, 'touchend', function (event) {
        if ((0, _element.hasClass)(event.target, 'topLeftSelectionHandle-HitArea')) {
          removeFromDragged.call(_this, 'topLeft');

          _this.touchStartRange = void 0;

          event.preventDefault();
          return false;
        } else if ((0, _element.hasClass)(event.target, 'bottomRightSelectionHandle-HitArea')) {
          removeFromDragged.call(_this, 'bottomRight');

          _this.touchStartRange = void 0;

          event.preventDefault();
          return false;
        }
      });

      this.eventManager.addEventListener(this.hot.rootElement, 'touchmove', function (event) {
        var scrollTop = (0, _element.getWindowScrollTop)(),
            scrollLeft = (0, _element.getWindowScrollLeft)(),
            endTarget = void 0,
            targetCoords = void 0,
            selectedRange = void 0,
            rangeWidth = void 0,
            rangeHeight = void 0,
            rangeDirection = void 0,
            newRangeCoords = void 0;

        if (_this.dragged.length === 0) {
          return;
        }

        endTarget = document.elementFromPoint(event.touches[0].screenX - scrollLeft, event.touches[0].screenY - scrollTop);

        if (!endTarget || endTarget === _this.lastSetCell) {
          return;
        }

        if (endTarget.nodeName == 'TD' || endTarget.nodeName == 'TH') {
          targetCoords = _this.hot.getCoords(endTarget);

          if (targetCoords.col == -1) {
            targetCoords.col = 0;
          }

          selectedRange = _this.hot.getSelectedRange();
          rangeWidth = selectedRange.getWidth();
          rangeHeight = selectedRange.getHeight();
          rangeDirection = selectedRange.getDirection();

          if (rangeWidth == 1 && rangeHeight == 1) {
            _this.hot.selection.setRangeEnd(targetCoords);
          }

          newRangeCoords = _this.getCurrentRangeCoords(selectedRange, targetCoords, _this.touchStartRange.direction, rangeDirection, _this.dragged[0]);

          if (newRangeCoords.start !== null) {
            _this.hot.selection.setRangeStart(newRangeCoords.start);
          }

          _this.hot.selection.setRangeEnd(newRangeCoords.end);

          _this.lastSetCell = endTarget;
        }

        event.preventDefault();
      });
    }
  }, {
    key: 'getCurrentRangeCoords',
    value: function getCurrentRangeCoords(selectedRange, currentTouch, touchStartDirection, currentDirection, draggedHandle) {
      var topLeftCorner = selectedRange.getTopLeftCorner(),
          bottomRightCorner = selectedRange.getBottomRightCorner(),
          bottomLeftCorner = selectedRange.getBottomLeftCorner(),
          topRightCorner = selectedRange.getTopRightCorner();

      var newCoords = {
        start: null,
        end: null
      };

      switch (touchStartDirection) {
        case 'NE-SW':
          switch (currentDirection) {
            case 'NE-SW':
            case 'NW-SE':
              if (draggedHandle == 'topLeft') {
                newCoords = {
                  start: new _src.CellCoords(currentTouch.row, selectedRange.highlight.col),
                  end: new _src.CellCoords(bottomLeftCorner.row, currentTouch.col)
                };
              } else {
                newCoords = {
                  start: new _src.CellCoords(selectedRange.highlight.row, currentTouch.col),
                  end: new _src.CellCoords(currentTouch.row, topLeftCorner.col)
                };
              }
              break;
            case 'SE-NW':
              if (draggedHandle == 'bottomRight') {
                newCoords = {
                  start: new _src.CellCoords(bottomRightCorner.row, currentTouch.col),
                  end: new _src.CellCoords(currentTouch.row, topLeftCorner.col)
                };
              }
              break;
            default:
              break;
          }
          break;
        case 'NW-SE':
          switch (currentDirection) {
            case 'NE-SW':
              if (draggedHandle == 'topLeft') {
                newCoords = {
                  start: currentTouch,
                  end: bottomLeftCorner
                };
              } else {
                newCoords.end = currentTouch;
              }
              break;
            case 'NW-SE':
              if (draggedHandle == 'topLeft') {
                newCoords = {
                  start: currentTouch,
                  end: bottomRightCorner
                };
              } else {
                newCoords.end = currentTouch;
              }
              break;
            case 'SE-NW':
              if (draggedHandle == 'topLeft') {
                newCoords = {
                  start: currentTouch,
                  end: topLeftCorner
                };
              } else {
                newCoords.end = currentTouch;
              }
              break;
            case 'SW-NE':
              if (draggedHandle == 'topLeft') {
                newCoords = {
                  start: currentTouch,
                  end: topRightCorner
                };
              } else {
                newCoords.end = currentTouch;
              }
              break;
            default:
              break;
          }
          break;
        case 'SW-NE':
          switch (currentDirection) {
            case 'NW-SE':
              if (draggedHandle == 'bottomRight') {
                newCoords = {
                  start: new _src.CellCoords(currentTouch.row, topLeftCorner.col),
                  end: new _src.CellCoords(bottomLeftCorner.row, currentTouch.col)
                };
              } else {
                newCoords = {
                  start: new _src.CellCoords(topLeftCorner.row, currentTouch.col),
                  end: new _src.CellCoords(currentTouch.row, bottomRightCorner.col)
                };
              }
              break;
            // case 'NE-SW':
            //
            //  break;
            case 'SW-NE':
              if (draggedHandle == 'topLeft') {
                newCoords = {
                  start: new _src.CellCoords(selectedRange.highlight.row, currentTouch.col),
                  end: new _src.CellCoords(currentTouch.row, bottomRightCorner.col)
                };
              } else {
                newCoords = {
                  start: new _src.CellCoords(currentTouch.row, topLeftCorner.col),
                  end: new _src.CellCoords(topLeftCorner.row, currentTouch.col)
                };
              }
              break;
            case 'SE-NW':
              if (draggedHandle == 'bottomRight') {
                newCoords = {
                  start: new _src.CellCoords(currentTouch.row, topRightCorner.col),
                  end: new _src.CellCoords(topLeftCorner.row, currentTouch.col)
                };
              } else if (draggedHandle == 'topLeft') {
                newCoords = {
                  start: bottomLeftCorner,
                  end: currentTouch
                };
              }
              break;
            default:
              break;
          }
          break;
        case 'SE-NW':
          switch (currentDirection) {
            case 'NW-SE':
            case 'NE-SW':
            case 'SW-NE':
              if (draggedHandle == 'topLeft') {
                newCoords.end = currentTouch;
              }
              break;
            case 'SE-NW':
              if (draggedHandle == 'topLeft') {
                newCoords.end = currentTouch;
              } else {
                newCoords = {
                  start: currentTouch,
                  end: topLeftCorner
                };
              }
              break;
            default:
              break;
          }
          break;
        default:
          break;
      }

      return newCoords;
    }

    /**
     * Check if user is currently dragging the handle.
     *
     * @returns {boolean} Dragging state
     */

  }, {
    key: 'isDragged',
    value: function isDragged() {
      return this.dragged.length > 0;
    }
  }]);

  return MultipleSelectionHandles;
}(_base2.default);

(0, _plugins.registerPlugin)('multipleSelectionHandles', MultipleSelectionHandles);

exports.default = MultipleSelectionHandles;

/***/ }),
/* 375 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


exports.__esModule = true;

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

var _pluginHooks = __webpack_require__(11);

var _pluginHooks2 = _interopRequireDefault(_pluginHooks);

var _element = __webpack_require__(0);

var _renderers = __webpack_require__(6);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

/**
 * @private
 * @plugin Search
 */
function Search(instance) {
  this.query = function (queryStr, callback, queryMethod) {
    var rowCount = instance.countRows();
    var colCount = instance.countCols();
    var queryResult = [];

    if (!callback) {
      callback = Search.global.getDefaultCallback();
    }

    if (!queryMethod) {
      queryMethod = Search.global.getDefaultQueryMethod();
    }

    for (var rowIndex = 0; rowIndex < rowCount; rowIndex++) {
      for (var colIndex = 0; colIndex < colCount; colIndex++) {
        var cellData = instance.getDataAtCell(rowIndex, colIndex);
        var cellProperties = instance.getCellMeta(rowIndex, colIndex);
        var cellCallback = cellProperties.search.callback || callback;
        var cellQueryMethod = cellProperties.search.queryMethod || queryMethod;
        var testResult = cellQueryMethod(queryStr, cellData);

        if (testResult) {
          var singleResult = {
            row: rowIndex,
            col: colIndex,
            data: cellData
          };

          queryResult.push(singleResult);
        }

        if (cellCallback) {
          cellCallback(instance, rowIndex, colIndex, cellData, testResult);
        }
      }
    }

    return queryResult;
  };
};

Search.DEFAULT_CALLBACK = function (instance, row, col, data, testResult) {
  instance.getCellMeta(row, col).isSearchResult = testResult;
};

Search.DEFAULT_QUERY_METHOD = function (query, value) {
  if (typeof query == 'undefined' || query == null || !query.toLowerCase || query.length === 0) {
    return false;
  }
  if (typeof value == 'undefined' || value == null) {
    return false;
  }

  return value.toString().toLowerCase().indexOf(query.toLowerCase()) != -1;
};

Search.DEFAULT_SEARCH_RESULT_CLASS = 'htSearchResult';

Search.global = function () {

  var defaultCallback = Search.DEFAULT_CALLBACK;
  var defaultQueryMethod = Search.DEFAULT_QUERY_METHOD;
  var defaultSearchResultClass = Search.DEFAULT_SEARCH_RESULT_CLASS;

  return {
    getDefaultCallback: function getDefaultCallback() {
      return defaultCallback;
    },
    setDefaultCallback: function setDefaultCallback(newDefaultCallback) {
      defaultCallback = newDefaultCallback;
    },
    getDefaultQueryMethod: function getDefaultQueryMethod() {
      return defaultQueryMethod;
    },
    setDefaultQueryMethod: function setDefaultQueryMethod(newDefaultQueryMethod) {
      defaultQueryMethod = newDefaultQueryMethod;
    },
    getDefaultSearchResultClass: function getDefaultSearchResultClass() {
      return defaultSearchResultClass;
    },
    setDefaultSearchResultClass: function setDefaultSearchResultClass(newSearchResultClass) {
      defaultSearchResultClass = newSearchResultClass;
    }
  };
}();

function SearchCellDecorator(instance, TD, row, col, prop, value, cellProperties) {
  var searchResultClass = cellProperties.search !== null && _typeof(cellProperties.search) == 'object' && cellProperties.search.searchResultClass || Search.global.getDefaultSearchResultClass();

  if (cellProperties.isSearchResult) {
    (0, _element.addClass)(TD, searchResultClass);
  } else {
    (0, _element.removeClass)(TD, searchResultClass);
  }
};

var originalBaseRenderer = (0, _renderers.getRenderer)('base');

(0, _renderers.registerRenderer)('base', function (instance, TD, row, col, prop, value, cellProperties) {
  originalBaseRenderer.apply(this, arguments);
  SearchCellDecorator.apply(this, arguments);
});

function init() {
  var instance = this;

  var pluginEnabled = !!instance.getSettings().search;

  if (pluginEnabled) {
    instance.search = new Search(instance);
  } else {
    delete instance.search;
  }
}

_pluginHooks2.default.getSingleton().add('afterInit', init);
_pluginHooks2.default.getSingleton().add('afterUpdateSettings', init);

exports.default = Search;

/***/ }),
/* 376 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


exports.__esModule = true;

var _element = __webpack_require__(0);

function cellDecorator(instance, TD, row, col, prop, value, cellProperties) {
  if (cellProperties.className) {
    if (TD.className) {
      TD.className = TD.className + ' ' + cellProperties.className;
    } else {
      TD.className = cellProperties.className;
    }
  }

  if (cellProperties.readOnly) {
    (0, _element.addClass)(TD, cellProperties.readOnlyCellClassName);
  }

  if (cellProperties.valid === false && cellProperties.invalidCellClassName) {
    (0, _element.addClass)(TD, cellProperties.invalidCellClassName);
  } else {
    (0, _element.removeClass)(TD, cellProperties.invalidCellClassName);
  }

  if (cellProperties.wordWrap === false && cellProperties.noWordWrapClassName) {
    (0, _element.addClass)(TD, cellProperties.noWordWrapClassName);
  }

  if (!value && cellProperties.placeholder) {
    (0, _element.addClass)(TD, cellProperties.placeholderCellClassName);
  }
} /**
   * Adds appropriate CSS class to table cell, based on cellProperties
   */
exports.default = cellDecorator;

/***/ }),
/* 377 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


exports.__esModule = true;

var _element = __webpack_require__(0);

var _eventManager = __webpack_require__(4);

var _eventManager2 = _interopRequireDefault(_eventManager);

var _src = __webpack_require__(14);

var _index = __webpack_require__(6);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

var clonableWRAPPER = document.createElement('DIV');
clonableWRAPPER.className = 'htAutocompleteWrapper';

var clonableARROW = document.createElement('DIV');
clonableARROW.className = 'htAutocompleteArrow';
// workaround for https://github.com/handsontable/handsontable/issues/1946
// this is faster than innerHTML. See: https://github.com/handsontable/handsontable/wiki/JavaScript-&-DOM-performance-tips
clonableARROW.appendChild(document.createTextNode(String.fromCharCode(9660)));

var wrapTdContentWithWrapper = function wrapTdContentWithWrapper(TD, WRAPPER) {
  WRAPPER.innerHTML = TD.innerHTML;
  (0, _element.empty)(TD);
  TD.appendChild(WRAPPER);
};

/**
 * Autocomplete renderer
 *
 * @private
 * @renderer AutocompleteRenderer
 * @param {Object} instance Handsontable instance
 * @param {Element} TD Table cell where to render
 * @param {Number} row
 * @param {Number} col
 * @param {String|Number} prop Row object property name
 * @param value Value to render (remember to escape unsafe HTML before inserting to DOM!)
 * @param {Object} cellProperties Cell properites (shared by cell renderer and editor)
 */
function autocompleteRenderer(instance, TD, row, col, prop, value, cellProperties) {
  var WRAPPER = clonableWRAPPER.cloneNode(true); // this is faster than createElement
  var ARROW = clonableARROW.cloneNode(true); // this is faster than createElement

  if (cellProperties.allowHtml) {
    (0, _index.getRenderer)('html').apply(this, arguments);
  } else {
    (0, _index.getRenderer)('text').apply(this, arguments);
  }

  TD.appendChild(ARROW);
  (0, _element.addClass)(TD, 'htAutocomplete');

  if (!TD.firstChild) {
    // http://jsperf.com/empty-node-if-needed
    // otherwise empty fields appear borderless in demo/renderers.html (IE)
    TD.appendChild(document.createTextNode(String.fromCharCode(160))); // workaround for https://github.com/handsontable/handsontable/issues/1946
    // this is faster than innerHTML. See: https://github.com/handsontable/handsontable/wiki/JavaScript-&-DOM-performance-tips
  }

  if (!instance.acArrowListener) {
    var eventManager = new _eventManager2.default(instance);

    // not very elegant but easy and fast
    instance.acArrowListener = function (event) {
      if ((0, _element.hasClass)(event.target, 'htAutocompleteArrow')) {
        instance.view.wt.getSetting('onCellDblClick', null, new _src.CellCoords(row, col), TD);
      }
    };

    eventManager.addEventListener(instance.rootElement, 'mousedown', instance.acArrowListener);

    // We need to unbind the listener after the table has been destroyed
    instance.addHookOnce('afterDestroy', function () {
      eventManager.destroy();
    });
  }
}

exports.default = autocompleteRenderer;

/***/ }),
/* 378 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


exports.__esModule = true;

var _element = __webpack_require__(0);

var _string = __webpack_require__(28);

var _eventManager = __webpack_require__(4);

var _eventManager2 = _interopRequireDefault(_eventManager);

var _unicode = __webpack_require__(15);

var _function = __webpack_require__(35);

var _event = __webpack_require__(7);

var _index = __webpack_require__(6);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

var isListeningKeyDownEvent = new WeakMap();
var isCheckboxListenerAdded = new WeakMap();
var BAD_VALUE_CLASS = 'htBadValue';

/**
 * Checkbox renderer
 *
 * @private
 * @param {Object} instance Handsontable instance
 * @param {Element} TD Table cell where to render
 * @param {Number} row
 * @param {Number} col
 * @param {String|Number} prop Row object property name
 * @param value Value to render (remember to escape unsafe HTML before inserting to DOM!)
 * @param {Object} cellProperties Cell properties (shared by cell renderer and editor)
 */
function checkboxRenderer(instance, TD, row, col, prop, value, cellProperties) {
  (0, _index.getRenderer)('base').apply(this, arguments);

  var eventManager = registerEvents(instance);
  var input = createInput();
  var labelOptions = cellProperties.label;
  var badValue = false;

  if (typeof cellProperties.checkedTemplate === 'undefined') {
    cellProperties.checkedTemplate = true;
  }
  if (typeof cellProperties.uncheckedTemplate === 'undefined') {
    cellProperties.uncheckedTemplate = false;
  }

  (0, _element.empty)(TD); // TODO identify under what circumstances this line can be removed

  if (value === cellProperties.checkedTemplate || (0, _string.equalsIgnoreCase)(value, cellProperties.checkedTemplate)) {
    input.checked = true;
  } else if (value === cellProperties.uncheckedTemplate || (0, _string.equalsIgnoreCase)(value, cellProperties.uncheckedTemplate)) {
    input.checked = false;
  } else if (value === null) {
    // default value
    (0, _element.addClass)(input, 'noValue');
  } else {
    input.style.display = 'none';
    (0, _element.addClass)(input, BAD_VALUE_CLASS);
    badValue = true;
  }

  input.setAttribute('data-row', row);
  input.setAttribute('data-col', col);

  if (!badValue && labelOptions) {
    var labelText = '';

    if (labelOptions.value) {
      labelText = typeof labelOptions.value === 'function' ? labelOptions.value.call(this, row, col, prop, value) : labelOptions.value;
    } else if (labelOptions.property) {
      labelText = instance.getDataAtRowProp(row, labelOptions.property);
    }
    var label = createLabel(labelText);

    if (labelOptions.position === 'before') {
      label.appendChild(input);
    } else {
      label.insertBefore(input, label.firstChild);
    }
    input = label;
  }

  TD.appendChild(input);

  if (badValue) {
    TD.appendChild(document.createTextNode('#bad-value#'));
  }

  if (!isListeningKeyDownEvent.has(instance)) {
    isListeningKeyDownEvent.set(instance, true);
    instance.addHook('beforeKeyDown', onBeforeKeyDown);
  }

  /**
   * On before key down DOM listener.
   *
   * @private
   * @param {Event} event
   */
  function onBeforeKeyDown(event) {
    var toggleKeys = 'SPACE|ENTER';
    var switchOffKeys = 'DELETE|BACKSPACE';
    var isKeyCode = (0, _function.partial)(_unicode.isKey, event.keyCode);

    if (isKeyCode(toggleKeys + '|' + switchOffKeys) && !(0, _event.isImmediatePropagationStopped)(event)) {
      eachSelectedCheckboxCell(function () {
        (0, _event.stopImmediatePropagation)(event);
        event.preventDefault();
      });
    }
    if (isKeyCode(toggleKeys)) {
      changeSelectedCheckboxesState();
    }
    if (isKeyCode(switchOffKeys)) {
      changeSelectedCheckboxesState(true);
    }
  }

  /**
   * Change checkbox checked property
   *
   * @private
   * @param {Boolean} [uncheckCheckbox=false]
   */
  function changeSelectedCheckboxesState() {
    var uncheckCheckbox = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;

    var selRange = instance.getSelectedRange();

    if (!selRange) {
      return;
    }

    var topLeft = selRange.getTopLeftCorner();
    var bottomRight = selRange.getBottomRightCorner();
    var changes = [];

    for (var _row = topLeft.row; _row <= bottomRight.row; _row += 1) {
      for (var _col = topLeft.col; _col <= bottomRight.col; _col += 1) {
        var _cellProperties = instance.getCellMeta(_row, _col);

        if (_cellProperties.type !== 'checkbox') {
          return;
        }

        /* eslint-disable no-continue */
        if (_cellProperties.readOnly === true) {
          continue;
        }

        if (typeof _cellProperties.checkedTemplate === 'undefined') {
          _cellProperties.checkedTemplate = true;
        }
        if (typeof _cellProperties.uncheckedTemplate === 'undefined') {
          _cellProperties.uncheckedTemplate = false;
        }

        var dataAtCell = instance.getDataAtCell(_row, _col);

        if (uncheckCheckbox === false) {
          if (dataAtCell === _cellProperties.checkedTemplate) {
            changes.push([_row, _col, _cellProperties.uncheckedTemplate]);
          } else if ([_cellProperties.uncheckedTemplate, null, void 0].indexOf(dataAtCell) !== -1) {
            changes.push([_row, _col, _cellProperties.checkedTemplate]);
          }
        } else {
          changes.push([_row, _col, _cellProperties.uncheckedTemplate]);
        }
      }
    }

    if (changes.length > 0) {
      instance.setDataAtCell(changes);
    }
  }

  /**
   * Call callback for each found selected cell with checkbox type.
   *
   * @private
   * @param {Function} callback
   */
  function eachSelectedCheckboxCell(callback) {
    var selRange = instance.getSelectedRange();

    if (!selRange) {
      return;
    }
    var topLeft = selRange.getTopLeftCorner();
    var bottomRight = selRange.getBottomRightCorner();

    for (var _row2 = topLeft.row; _row2 <= bottomRight.row; _row2++) {
      for (var _col2 = topLeft.col; _col2 <= bottomRight.col; _col2++) {
        var _cellProperties2 = instance.getCellMeta(_row2, _col2);

        if (_cellProperties2.type !== 'checkbox') {
          return;
        }

        var cell = instance.getCell(_row2, _col2);

        if (cell == null) {

          callback(_row2, _col2, _cellProperties2);
        } else {
          var checkboxes = cell.querySelectorAll('input[type=checkbox]');

          if (checkboxes.length > 0 && !_cellProperties2.readOnly) {
            callback(checkboxes);
          }
        }
      }
    }
  }
}

/**
 * Register checkbox listeners.
 *
 * @param {Handsontable} instance Handsontable instance.
 * @returns {EventManager}
 */
function registerEvents(instance) {
  var eventManager = isCheckboxListenerAdded.get(instance);

  if (!eventManager) {
    eventManager = new _eventManager2.default(instance);
    eventManager.addEventListener(instance.rootElement, 'click', function (event) {
      return onClick(event, instance);
    });
    eventManager.addEventListener(instance.rootElement, 'mouseup', function (event) {
      return onMouseUp(event, instance);
    });
    eventManager.addEventListener(instance.rootElement, 'change', function (event) {
      return onChange(event, instance);
    });

    isCheckboxListenerAdded.set(instance, eventManager);
  }

  return eventManager;
}

/**
 * Create input element.
 *
 * @returns {Node}
 */
function createInput() {
  var input = document.createElement('input');

  input.className = 'htCheckboxRendererInput';
  input.type = 'checkbox';
  input.setAttribute('autocomplete', 'off');
  input.setAttribute('tabindex', '-1');

  return input.cloneNode(false);
}

/**
 * Create label element.
 *
 * @returns {Node}
 */
function createLabel(text) {
  var label = document.createElement('label');

  label.className = 'htCheckboxRendererLabel';
  label.appendChild(document.createTextNode(text));

  return label.cloneNode(true);
}

/**
 * `mouseup` callback.
 *
 * @private
 * @param {Event} event `mouseup` event.
 * @param {Object} instance Handsontable instance.
 */
function onMouseUp(event, instance) {
  if (!isCheckboxInput(event.target)) {
    return;
  }
  setTimeout(instance.listen, 10);
}

/**
 * `click` callback.
 *
 * @private
 * @param {Event} event `click` event.
 * @param {Object} instance Handsontable instance.
 */
function onClick(event, instance) {
  if (!isCheckboxInput(event.target)) {
    return false;
  }

  var row = parseInt(event.target.getAttribute('data-row'), 10);
  var col = parseInt(event.target.getAttribute('data-col'), 10);
  var cellProperties = instance.getCellMeta(row, col);

  if (cellProperties.readOnly) {
    event.preventDefault();
  }
}

/**
 * `change` callback.
 *
 * @param {Event} event `change` event.
 * @param {Object} instance Handsontable instance.
 * @param {Object} cellProperties Reference to cell properties.
 * @returns {Boolean}
 */
function onChange(event, instance) {
  if (!isCheckboxInput(event.target)) {
    return false;
  }

  var row = parseInt(event.target.getAttribute('data-row'), 10);
  var col = parseInt(event.target.getAttribute('data-col'), 10);
  var cellProperties = instance.getCellMeta(row, col);

  if (!cellProperties.readOnly) {
    var newCheckboxValue = null;

    if (event.target.checked) {
      newCheckboxValue = cellProperties.uncheckedTemplate === void 0 ? true : cellProperties.checkedTemplate;
    } else {
      newCheckboxValue = cellProperties.uncheckedTemplate === void 0 ? false : cellProperties.uncheckedTemplate;
    }

    instance.setDataAtCell(row, col, newCheckboxValue);
  }
}

/**
 * Check if the provided element is the checkbox input.
 *
 * @private
 * @param {HTMLElement} element The element in question.
 * @returns {Boolean}
 */
function isCheckboxInput(element) {
  return element.tagName === 'INPUT' && element.getAttribute('type') === 'checkbox';
}

exports.default = checkboxRenderer;

/***/ }),
/* 379 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


exports.__esModule = true;

var _element = __webpack_require__(0);

var _index = __webpack_require__(6);

/**
 * @private
 * @renderer HtmlRenderer
 * @param instance
 * @param TD
 * @param row
 * @param col
 * @param prop
 * @param value
 * @param cellProperties
 */
function htmlRenderer(instance, TD, row, col, prop, value, cellProperties) {
  (0, _index.getRenderer)('base').apply(this, arguments);

  if (value === null || value === void 0) {
    value = '';
  }

  (0, _element.fastInnerHTML)(TD, value);
}

exports.default = htmlRenderer;

/***/ }),
/* 380 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


exports.__esModule = true;

var _numbro = __webpack_require__(52);

var _numbro2 = _interopRequireDefault(_numbro);

var _index = __webpack_require__(6);

var _number = __webpack_require__(5);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

/**
 * Numeric cell renderer
 *
 * @private
 * @renderer NumericRenderer
 * @dependencies numbro
 * @param {Object} instance Handsontable instance
 * @param {Element} TD Table cell where to render
 * @param {Number} row
 * @param {Number} col
 * @param {String|Number} prop Row object property name
 * @param value Value to render (remember to escape unsafe HTML before inserting to DOM!)
 * @param {Object} cellProperties Cell properties (shared by cell renderer and editor)
 */
function numericRenderer(instance, TD, row, col, prop, value, cellProperties) {
  if ((0, _number.isNumeric)(value)) {
    if (typeof cellProperties.language !== 'undefined') {
      _numbro2.default.culture(cellProperties.language);
    }

    value = (0, _numbro2.default)(value).format(cellProperties.format || '0');

    var className = cellProperties.className || '';

    var classArr = className.length ? className.split(' ') : [];

    if (classArr.indexOf('htLeft') < 0 && classArr.indexOf('htCenter') < 0 && classArr.indexOf('htRight') < 0 && classArr.indexOf('htJustify') < 0) {
      classArr.push('htRight');
    }

    if (classArr.indexOf('htNumeric') < 0) {
      classArr.push('htNumeric');
    }

    cellProperties.className = classArr.join(' ');
  }

  (0, _index.getRenderer)('text')(instance, TD, row, col, prop, value, cellProperties);
}

exports.default = numericRenderer;

/***/ }),
/* 381 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


exports.__esModule = true;

var _element = __webpack_require__(0);

var _index = __webpack_require__(6);

var _number = __webpack_require__(5);

/**
 * @private
 * @renderer PasswordRenderer
 * @param instance
 * @param TD
 * @param row
 * @param col
 * @param prop
 * @param value
 * @param cellProperties
 */
function passwordRenderer(instance, TD, row, col, prop, value, cellProperties) {
  (0, _index.getRenderer)('text').apply(this, arguments);

  value = TD.innerHTML;

  var hashLength = cellProperties.hashLength || value.length;
  var hashSymbol = cellProperties.hashSymbol || '*';

  var hash = '';

  (0, _number.rangeEach)(hashLength - 1, function () {
    hash += hashSymbol;
  });
  (0, _element.fastInnerHTML)(TD, hash);
}

exports.default = passwordRenderer;

/***/ }),
/* 382 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


exports.__esModule = true;

var _element = __webpack_require__(0);

var _mixed = __webpack_require__(23);

var _index = __webpack_require__(6);

/**
 * Default text renderer
 *
 * @private
 * @renderer TextRenderer
 * @param {Object} instance Handsontable instance
 * @param {Element} TD Table cell where to render
 * @param {Number} row
 * @param {Number} col
 * @param {String|Number} prop Row object property name
 * @param value Value to render (remember to escape unsafe HTML before inserting to DOM!)
 * @param {Object} cellProperties Cell properties (shared by cell renderer and editor)
 */
function textRenderer(instance, TD, row, col, prop, value, cellProperties) {
  (0, _index.getRenderer)('base').apply(this, arguments);

  if (!value && cellProperties.placeholder) {
    value = cellProperties.placeholder;
  }

  var escaped = (0, _mixed.stringify)(value);

  if (!instance.getSettings().trimWhitespace) {
    escaped = escaped.replace(/ /g, String.fromCharCode(160));
  }

  if (cellProperties.rendererTemplate) {
    (0, _element.empty)(TD);
    var TEMPLATE = document.createElement('TEMPLATE');
    TEMPLATE.setAttribute('bind', '{{}}');
    TEMPLATE.innerHTML = cellProperties.rendererTemplate;
    HTMLTemplateElement.decorate(TEMPLATE);
    TEMPLATE.model = instance.getSourceDataAtRow(row);
    TD.appendChild(TEMPLATE);
  } else {
    // this is faster than innerHTML. See: https://github.com/handsontable/handsontable/wiki/JavaScript-&-DOM-performance-tips
    (0, _element.fastInnerText)(TD, escaped);
  }
}

exports.default = textRenderer;

/***/ }),
/* 383 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


exports.__esModule = true;

var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }();

var _element = __webpack_require__(0);

var _browser = __webpack_require__(22);

var _eventManager = __webpack_require__(4);

var _eventManager2 = _interopRequireDefault(_eventManager);

var _event = __webpack_require__(7);

var _src = __webpack_require__(14);

var _src2 = _interopRequireDefault(_src);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

/**
 * Handsontable TableView constructor
 * @param {Object} instance
 */
function TableView(instance) {
  var _this = this;

  var that = this;

  this.eventManager = new _eventManager2.default(instance);
  this.instance = instance;
  this.settings = instance.getSettings();
  this.selectionMouseDown = false;

  var originalStyle = instance.rootElement.getAttribute('style');

  if (originalStyle) {
    instance.rootElement.setAttribute('data-originalstyle', originalStyle); // needed to retrieve original style in jsFiddle link generator in HT examples. may be removed in future versions
  }

  (0, _element.addClass)(instance.rootElement, 'handsontable');

  var table = document.createElement('TABLE');
  (0, _element.addClass)(table, 'htCore');

  if (instance.getSettings().tableClassName) {
    (0, _element.addClass)(table, instance.getSettings().tableClassName);
  }
  this.THEAD = document.createElement('THEAD');
  table.appendChild(this.THEAD);
  this.TBODY = document.createElement('TBODY');
  table.appendChild(this.TBODY);

  instance.table = table;

  instance.container.insertBefore(table, instance.container.firstChild);

  this.eventManager.addEventListener(instance.rootElement, 'mousedown', function (event) {
    this.selectionMouseDown = true;

    if (!that.isTextSelectionAllowed(event.target)) {
      clearTextSelection();
      event.preventDefault();
      window.focus(); // make sure that window that contains HOT is active. Important when HOT is in iframe.
    }
  });
  this.eventManager.addEventListener(instance.rootElement, 'mouseup', function (event) {
    this.selectionMouseDown = false;
  });
  this.eventManager.addEventListener(instance.rootElement, 'mousemove', function (event) {
    if (this.selectionMouseDown && !that.isTextSelectionAllowed(event.target)) {
      clearTextSelection();
      event.preventDefault();
    }
  });

  this.eventManager.addEventListener(document.documentElement, 'keyup', function (event) {
    if (instance.selection.isInProgress() && !event.shiftKey) {
      instance.selection.finish();
    }
  });

  var isMouseDown;
  this.isMouseDown = function () {
    return isMouseDown;
  };

  this.eventManager.addEventListener(document.documentElement, 'mouseup', function (event) {
    if (instance.selection.isInProgress() && event.which === 1) {
      // is left mouse button
      instance.selection.finish();
    }

    isMouseDown = false;

    if ((0, _element.isOutsideInput)(document.activeElement) || !instance.selection.isSelected()) {
      instance.unlisten();
    }
  });

  this.eventManager.addEventListener(document.documentElement, 'mousedown', function (event) {
    var originalTarget = event.target;
    var next = event.target;
    var eventX = event.x || event.clientX;
    var eventY = event.y || event.clientY;

    if (isMouseDown || !instance.rootElement) {
      return; // it must have been started in a cell
    }

    // immediate click on "holder" means click on the right side of vertical scrollbar
    if (next === instance.view.wt.wtTable.holder) {
      var scrollbarWidth = (0, _element.getScrollbarWidth)();

      if (document.elementFromPoint(eventX + scrollbarWidth, eventY) !== instance.view.wt.wtTable.holder || document.elementFromPoint(eventX, eventY + scrollbarWidth) !== instance.view.wt.wtTable.holder) {
        return;
      }
    } else {
      while (next !== document.documentElement) {
        if (next === null) {
          if (event.isTargetWebComponent) {
            break;
          }
          // click on something that was a row but now is detached (possibly because your click triggered a rerender)
          return;
        }
        if (next === instance.rootElement) {
          // click inside container
          return;
        }
        next = next.parentNode;
      }
    }

    // function did not return until here, we have an outside click!

    var outsideClickDeselects = typeof that.settings.outsideClickDeselects === 'function' ? that.settings.outsideClickDeselects(originalTarget) : that.settings.outsideClickDeselects;

    if (outsideClickDeselects) {
      instance.deselectCell();
    } else if (!jQuery(originalTarget).parents('#link__wiz,#tool__bar,.picker').length) {
      instance.destroyEditor();
    }
  });

  this.eventManager.addEventListener(table, 'selectstart', function (event) {
    if (that.settings.fragmentSelection || (0, _element.isInput)(event.target)) {
      return;
    }
    // https://github.com/handsontable/handsontable/issues/160
    // Prevent text from being selected when performing drag down.
    event.preventDefault();
  });

  var clearTextSelection = function clearTextSelection() {
    // http://stackoverflow.com/questions/3169786/clear-text-selection-with-javascript
    if (window.getSelection) {
      if (window.getSelection().empty) {
        // Chrome
        window.getSelection().empty();
      } else if (window.getSelection().removeAllRanges) {
        // Firefox
        window.getSelection().removeAllRanges();
      }
    } else if (document.selection) {
      // IE?
      document.selection.empty();
    }
  };

  var selections = [new _src.Selection({
    className: 'current',
    border: {
      width: 2,
      color: '#5292F7',
      // style: 'solid', // not used
      cornerVisible: function cornerVisible() {
        return that.settings.fillHandle && !that.isCellEdited() && !instance.selection.isMultiple();
      },
      multipleSelectionHandlesVisible: function multipleSelectionHandlesVisible() {
        return !that.isCellEdited() && !instance.selection.isMultiple();
      }
    }
  }), new _src.Selection({
    className: 'area',
    border: {
      width: 1,
      color: '#89AFF9',
      // style: 'solid', // not used
      cornerVisible: function cornerVisible() {
        return that.settings.fillHandle && !that.isCellEdited() && instance.selection.isMultiple();
      },
      multipleSelectionHandlesVisible: function multipleSelectionHandlesVisible() {
        return !that.isCellEdited() && instance.selection.isMultiple();
      }
    }
  }), new _src.Selection({
    className: 'highlight',
    highlightHeaderClassName: that.settings.currentHeaderClassName,
    highlightRowClassName: that.settings.currentRowClassName,
    highlightColumnClassName: that.settings.currentColClassName
  }), new _src.Selection({
    className: 'fill',
    border: {
      width: 1,
      color: 'red'
      // style: 'solid' // not used
    }
  })];
  selections.current = selections[0];
  selections.area = selections[1];
  selections.highlight = selections[2];
  selections.fill = selections[3];

  var walkontableConfig = {
    debug: function debug() {
      return that.settings.debug;
    },
    externalRowCalculator: this.instance.getPlugin('autoRowSize') && this.instance.getPlugin('autoRowSize').isEnabled(),
    table: table,
    preventOverflow: function preventOverflow() {
      return _this.settings.preventOverflow;
    },
    stretchH: function stretchH() {
      return that.settings.stretchH;
    },
    data: instance.getDataAtCell,
    totalRows: function totalRows() {
      return instance.countRows();
    },
    totalColumns: function totalColumns() {
      return instance.countCols();
    },
    fixedColumnsLeft: function fixedColumnsLeft() {
      return that.settings.fixedColumnsLeft;
    },
    fixedRowsTop: function fixedRowsTop() {
      return that.settings.fixedRowsTop;
    },
    fixedRowsBottom: function fixedRowsBottom() {
      return that.settings.fixedRowsBottom;
    },
    minSpareRows: function minSpareRows() {
      return that.settings.minSpareRows;
    },
    renderAllRows: that.settings.renderAllRows,
    rowHeaders: function rowHeaders() {
      var headerRenderers = [];

      if (instance.hasRowHeaders()) {
        headerRenderers.push(function (row, TH) {
          that.appendRowHeader(row, TH);
        });
      }
      instance.runHooks('afterGetRowHeaderRenderers', headerRenderers);

      return headerRenderers;
    },
    columnHeaders: function columnHeaders() {
      var headerRenderers = [];

      if (instance.hasColHeaders()) {
        headerRenderers.push(function (column, TH) {
          that.appendColHeader(column, TH);
        });
      }
      instance.runHooks('afterGetColumnHeaderRenderers', headerRenderers);

      return headerRenderers;
    },
    columnWidth: instance.getColWidth,
    rowHeight: instance.getRowHeight,
    cellRenderer: function cellRenderer(row, col, TD) {
      var cellProperties = that.instance.getCellMeta(row, col);
      var prop = that.instance.colToProp(col);
      var value = that.instance.getDataAtRowProp(row, prop);

      if (that.instance.hasHook('beforeValueRender')) {
        value = that.instance.runHooks('beforeValueRender', value);
      }

      that.instance.runHooks('beforeRenderer', TD, row, col, prop, value, cellProperties);
      that.instance.getCellRenderer(cellProperties)(that.instance, TD, row, col, prop, value, cellProperties);
      that.instance.runHooks('afterRenderer', TD, row, col, prop, value, cellProperties);
    },
    selections: selections,
    hideBorderOnMouseDownOver: function hideBorderOnMouseDownOver() {
      return that.settings.fragmentSelection;
    },
    onCellMouseDown: function onCellMouseDown(event, coords, TD, wt) {
      var blockCalculations = {
        row: false,
        column: false,
        cells: false
      };

      instance.listen();

      that.activeWt = wt;
      isMouseDown = true;

      instance.runHooks('beforeOnCellMouseDown', event, coords, TD, blockCalculations);

      if ((0, _event.isImmediatePropagationStopped)(event)) {
        return;
      }

      var actualSelection = instance.getSelectedRange();
      var selection = instance.selection;
      var selectedHeader = selection.selectedHeader;

      if (event.shiftKey && actualSelection) {
        if (coords.row >= 0 && coords.col >= 0 && !blockCalculations.cells) {
          selection.setSelectedHeaders(false, false);
          selection.setRangeEnd(coords);
        } else if ((selectedHeader.cols || selectedHeader.rows) && coords.row >= 0 && coords.col >= 0 && !blockCalculations.cells) {
          selection.setSelectedHeaders(false, false);
          selection.setRangeEnd(new _src.CellCoords(coords.row, coords.col));
        } else if (selectedHeader.cols && coords.row < 0 && !blockCalculations.column) {
          selection.setRangeEnd(new _src.CellCoords(actualSelection.to.row, coords.col));
        } else if (selectedHeader.rows && coords.col < 0 && !blockCalculations.row) {
          selection.setRangeEnd(new _src.CellCoords(coords.row, actualSelection.to.col));
        } else if ((!selectedHeader.cols && !selectedHeader.rows && coords.col < 0 || selectedHeader.cols && coords.col < 0) && !blockCalculations.row) {
          selection.setSelectedHeaders(true, false);
          selection.setRangeStartOnly(new _src.CellCoords(actualSelection.from.row, 0));
          selection.setRangeEnd(new _src.CellCoords(coords.row, instance.countCols() - 1));
        } else if ((!selectedHeader.cols && !selectedHeader.rows && coords.row < 0 || selectedHeader.rows && coords.row < 0) && !blockCalculations.column) {
          selection.setSelectedHeaders(false, true);
          selection.setRangeStartOnly(new _src.CellCoords(0, actualSelection.from.col));
          selection.setRangeEnd(new _src.CellCoords(instance.countRows() - 1, coords.col));
        }
      } else {
        var doNewSelection = true;

        if (actualSelection) {
          var from = actualSelection.from,
              to = actualSelection.to;

          var coordsNotInSelection = !selection.inInSelection(coords);

          if (coords.row < 0 && selectedHeader.cols) {
            var start = Math.min(from.col, to.col);
            var end = Math.max(from.col, to.col);

            doNewSelection = coords.col < start || coords.col > end;
          } else if (coords.col < 0 && selectedHeader.rows) {
            var _start = Math.min(from.row, to.row);
            var _end = Math.max(from.row, to.row);

            doNewSelection = coords.row < _start || coords.row > _end;
          } else {
            doNewSelection = coordsNotInSelection;
          }
        }

        var rightClick = (0, _event.isRightClick)(event);
        var leftClick = (0, _event.isLeftClick)(event) || event.type === 'touchstart';

        // clicked row header and when some column was selected
        if (coords.row < 0 && coords.col >= 0 && !blockCalculations.column) {
          selection.setSelectedHeaders(false, true);

          if (leftClick || rightClick && doNewSelection) {
            selection.setRangeStartOnly(new _src.CellCoords(0, coords.col));
            selection.setRangeEnd(new _src.CellCoords(Math.max(instance.countRows() - 1, 0), coords.col), false);
          }

          // clicked column header and when some row was selected
        } else if (coords.col < 0 && coords.row >= 0 && !blockCalculations.row) {
          selection.setSelectedHeaders(true, false);

          if (leftClick || rightClick && doNewSelection) {
            selection.setRangeStartOnly(new _src.CellCoords(coords.row, 0));
            selection.setRangeEnd(new _src.CellCoords(coords.row, Math.max(instance.countCols() - 1, 0)), false);
          }
        } else if (coords.col >= 0 && coords.row >= 0 && !blockCalculations.cells) {
          if (leftClick || rightClick && doNewSelection) {
            selection.setSelectedHeaders(false, false);
            selection.setRangeStart(coords);
          }
        } else if (coords.col < 0 && coords.row < 0) {
          coords.row = 0;
          coords.col = 0;

          selection.setSelectedHeaders(false, false, true);
          selection.setRangeStart(coords);
        }
      }

      instance.runHooks('afterOnCellMouseDown', event, coords, TD);
      that.activeWt = that.wt;
    },
    onCellMouseOut: function onCellMouseOut(event, coords, TD, wt) {
      that.activeWt = wt;
      instance.runHooks('beforeOnCellMouseOut', event, coords, TD);

      if ((0, _event.isImmediatePropagationStopped)(event)) {
        return;
      }

      instance.runHooks('afterOnCellMouseOut', event, coords, TD);
      that.activeWt = that.wt;
    },
    onCellMouseOver: function onCellMouseOver(event, coords, TD, wt) {
      var blockCalculations = {
        row: false,
        column: false,
        cell: false
      };

      that.activeWt = wt;
      instance.runHooks('beforeOnCellMouseOver', event, coords, TD, blockCalculations);

      if ((0, _event.isImmediatePropagationStopped)(event)) {
        return;
      }

      if (event.button === 0 && isMouseDown) {
        if (coords.row >= 0 && coords.col >= 0) {
          // is not a header
          if (instance.selection.selectedHeader.cols && !blockCalculations.column) {
            instance.selection.setRangeEnd(new _src.CellCoords(instance.countRows() - 1, coords.col), false);
          } else if (instance.selection.selectedHeader.rows && !blockCalculations.row) {
            instance.selection.setRangeEnd(new _src.CellCoords(coords.row, instance.countCols() - 1), false);
          } else if (!blockCalculations.cell) {
            instance.selection.setRangeEnd(coords);
          }
        } else {
          /* eslint-disable no-lonely-if */
          if (instance.selection.selectedHeader.cols && !blockCalculations.column) {
            instance.selection.setRangeEnd(new _src.CellCoords(instance.countRows() - 1, coords.col), false);
          } else if (instance.selection.selectedHeader.rows && !blockCalculations.row) {
            instance.selection.setRangeEnd(new _src.CellCoords(coords.row, instance.countCols() - 1), false);
          } else if (!blockCalculations.cell) {
            instance.selection.setRangeEnd(coords);
          }
        }
      }

      instance.runHooks('afterOnCellMouseOver', event, coords, TD);
      that.activeWt = that.wt;
    },
    onCellMouseUp: function onCellMouseUp(event, coords, TD, wt) {
      that.activeWt = wt;
      instance.runHooks('beforeOnCellMouseUp', event, coords, TD);

      instance.runHooks('afterOnCellMouseUp', event, coords, TD);
      that.activeWt = that.wt;
    },
    onCellCornerMouseDown: function onCellCornerMouseDown(event) {
      event.preventDefault();
      instance.runHooks('afterOnCellCornerMouseDown', event);
    },
    onCellCornerDblClick: function onCellCornerDblClick(event) {
      event.preventDefault();
      instance.runHooks('afterOnCellCornerDblClick', event);
    },
    beforeDraw: function beforeDraw(force, skipRender) {
      that.beforeRender(force, skipRender);
    },
    onDraw: function onDraw(force) {
      that.onDraw(force);
    },
    onScrollVertically: function onScrollVertically() {
      instance.runHooks('afterScrollVertically');
    },
    onScrollHorizontally: function onScrollHorizontally() {
      instance.runHooks('afterScrollHorizontally');
    },
    onBeforeDrawBorders: function onBeforeDrawBorders(corners, borderClassName) {
      instance.runHooks('beforeDrawBorders', corners, borderClassName);
    },
    onBeforeTouchScroll: function onBeforeTouchScroll() {
      instance.runHooks('beforeTouchScroll');
    },
    onAfterMomentumScroll: function onAfterMomentumScroll() {
      instance.runHooks('afterMomentumScroll');
    },
    onBeforeStretchingColumnWidth: function onBeforeStretchingColumnWidth(stretchedWidth, column) {
      return instance.runHooks('beforeStretchingColumnWidth', stretchedWidth, column);
    },
    onModifyRowHeaderWidth: function onModifyRowHeaderWidth(rowHeaderWidth) {
      return instance.runHooks('modifyRowHeaderWidth', rowHeaderWidth);
    },
    viewportRowCalculatorOverride: function viewportRowCalculatorOverride(calc) {
      var rows = instance.countRows();
      var viewportOffset = that.settings.viewportRowRenderingOffset;

      if (viewportOffset === 'auto' && that.settings.fixedRowsTop) {
        viewportOffset = 10;
      }
      if (typeof viewportOffset === 'number') {
        calc.startRow = Math.max(calc.startRow - viewportOffset, 0);
        calc.endRow = Math.min(calc.endRow + viewportOffset, rows - 1);
      }
      if (viewportOffset === 'auto') {
        var center = calc.startRow + calc.endRow - calc.startRow;
        var offset = Math.ceil(center / rows * 12);

        calc.startRow = Math.max(calc.startRow - offset, 0);
        calc.endRow = Math.min(calc.endRow + offset, rows - 1);
      }
      instance.runHooks('afterViewportRowCalculatorOverride', calc);
    },
    viewportColumnCalculatorOverride: function viewportColumnCalculatorOverride(calc) {
      var cols = instance.countCols();
      var viewportOffset = that.settings.viewportColumnRenderingOffset;

      if (viewportOffset === 'auto' && that.settings.fixedColumnsLeft) {
        viewportOffset = 10;
      }
      if (typeof viewportOffset === 'number') {
        calc.startColumn = Math.max(calc.startColumn - viewportOffset, 0);
        calc.endColumn = Math.min(calc.endColumn + viewportOffset, cols - 1);
      }
      if (viewportOffset === 'auto') {
        var center = calc.startColumn + calc.endColumn - calc.startColumn;
        var offset = Math.ceil(center / cols * 12);

        calc.startRow = Math.max(calc.startColumn - offset, 0);
        calc.endColumn = Math.min(calc.endColumn + offset, cols - 1);
      }
      instance.runHooks('afterViewportColumnCalculatorOverride', calc);
    },
    rowHeaderWidth: function rowHeaderWidth() {
      return that.settings.rowHeaderWidth;
    },
    columnHeaderHeight: function columnHeaderHeight() {
      var columnHeaderHeight = instance.runHooks('modifyColumnHeaderHeight');
      return that.settings.columnHeaderHeight || columnHeaderHeight;
    }
  };

  instance.runHooks('beforeInitWalkontable', walkontableConfig);

  this.wt = new _src2.default(walkontableConfig);
  this.activeWt = this.wt;

  if (!(0, _browser.isChrome)() && !(0, _browser.isSafari)()) {
    this.eventManager.addEventListener(instance.rootElement, 'wheel', function (event) {
      event.preventDefault();

      var lineHeight = parseInt((0, _element.getComputedStyle)(document.body)['font-size'], 10);
      var holder = that.wt.wtOverlays.scrollableElement;

      var deltaY = event.wheelDeltaY || event.deltaY;
      var deltaX = event.wheelDeltaX || event.deltaX;

      switch (event.deltaMode) {
        case 0:
          holder.scrollLeft += deltaX;
          holder.scrollTop += deltaY;
          break;

        case 1:
          holder.scrollLeft += deltaX * lineHeight;
          holder.scrollTop += deltaY * lineHeight;
          break;

        default:
          break;
      }
    });
  }

  this.eventManager.addEventListener(that.wt.wtTable.spreader, 'mousedown', function (event) {
    // right mouse button exactly on spreader means right click on the right hand side of vertical scrollbar
    if (event.target === that.wt.wtTable.spreader && event.which === 3) {
      (0, _event.stopPropagation)(event);
    }
  });

  this.eventManager.addEventListener(that.wt.wtTable.spreader, 'contextmenu', function (event) {
    // right mouse button exactly on spreader means right click on the right hand side of vertical scrollbar
    if (event.target === that.wt.wtTable.spreader && event.which === 3) {
      (0, _event.stopPropagation)(event);
    }
  });

  this.eventManager.addEventListener(document.documentElement, 'click', function () {
    if (that.settings.observeDOMVisibility) {
      if (that.wt.drawInterrupted) {
        that.instance.forceFullRender = true;
        that.render();
      }
    }
  });
}

TableView.prototype.isTextSelectionAllowed = function (el) {
  if ((0, _element.isInput)(el)) {
    return true;
  }
  var isChildOfTableBody = (0, _element.isChildOf)(el, this.instance.view.wt.wtTable.spreader);

  if (this.settings.fragmentSelection === true && isChildOfTableBody) {
    return true;
  }
  if (this.settings.fragmentSelection === 'cell' && this.isSelectedOnlyCell() && isChildOfTableBody) {
    return true;
  }
  if (!this.settings.fragmentSelection && this.isCellEdited() && this.isSelectedOnlyCell()) {
    return true;
  }

  return false;
};

/**
 * Check if selected only one cell.
 *
 * @returns {Boolean}
 */
TableView.prototype.isSelectedOnlyCell = function () {
  var _ref = this.instance.getSelected() || [],
      _ref2 = _slicedToArray(_ref, 4),
      row = _ref2[0],
      col = _ref2[1],
      rowEnd = _ref2[2],
      colEnd = _ref2[3];

  return row !== void 0 && row === rowEnd && col === colEnd;
};

TableView.prototype.isCellEdited = function () {
  var activeEditor = this.instance.getActiveEditor();

  return activeEditor && activeEditor.isOpened();
};

TableView.prototype.beforeRender = function (force, skipRender) {
  if (force) {
    // this.instance.forceFullRender = did Handsontable request full render?
    this.instance.runHooks('beforeRender', this.instance.forceFullRender, skipRender);
  }
};

TableView.prototype.onDraw = function (force) {
  if (force) {
    // this.instance.forceFullRender = did Handsontable request full render?
    this.instance.runHooks('afterRender', this.instance.forceFullRender);
  }
};

TableView.prototype.render = function () {
  this.wt.draw(!this.instance.forceFullRender);
  this.instance.forceFullRender = false;
  this.instance.renderCall = false;
};

/**
 * Returns td object given coordinates
 *
 * @param {CellCoords} coords
 * @param {Boolean} topmost
 */
TableView.prototype.getCellAtCoords = function (coords, topmost) {
  var td = this.wt.getCell(coords, topmost);

  if (td < 0) {
    // there was an exit code (cell is out of bounds)
    return null;
  }

  return td;
};

/**
 * Scroll viewport to selection.
 *
 * @param {CellCoords} coords
 */
TableView.prototype.scrollViewport = function (coords) {
  this.wt.scrollViewport(coords);
};

/**
 * Append row header to a TH element
 * @param row
 * @param TH
 */
TableView.prototype.appendRowHeader = function (row, TH) {
  if (TH.firstChild) {
    var container = TH.firstChild;

    if (!(0, _element.hasClass)(container, 'relative')) {
      (0, _element.empty)(TH);
      this.appendRowHeader(row, TH);

      return;
    }
    this.updateCellHeader(container.querySelector('.rowHeader'), row, this.instance.getRowHeader);
  } else {
    var div = document.createElement('div');
    var span = document.createElement('span');

    div.className = 'relative';
    span.className = 'rowHeader';
    this.updateCellHeader(span, row, this.instance.getRowHeader);

    div.appendChild(span);
    TH.appendChild(div);
  }

  this.instance.runHooks('afterGetRowHeader', row, TH);
};

/**
 * Append column header to a TH element
 * @param col
 * @param TH
 */
TableView.prototype.appendColHeader = function (col, TH) {
  if (TH.firstChild) {
    var container = TH.firstChild;

    if ((0, _element.hasClass)(container, 'relative')) {
      this.updateCellHeader(container.querySelector('.colHeader'), col, this.instance.getColHeader);
    } else {
      (0, _element.empty)(TH);
      this.appendColHeader(col, TH);
    }
  } else {
    var div = document.createElement('div');
    var span = document.createElement('span');

    div.className = 'relative';
    span.className = 'colHeader';
    this.updateCellHeader(span, col, this.instance.getColHeader);

    div.appendChild(span);
    TH.appendChild(div);
  }

  this.instance.runHooks('afterGetColHeader', col, TH);
};

/**
 * Update header cell content
 *
 * @since 0.15.0-beta4
 * @param {HTMLElement} element Element to update
 * @param {Number} index Row index or column index
 * @param {Function} content Function which should be returns content for this cell
 */
TableView.prototype.updateCellHeader = function (element, index, content) {
  var renderedIndex = index;
  var parentOverlay = this.wt.wtOverlays.getParentOverlay(element) || this.wt;

  // prevent wrong calculations from SampleGenerator
  if (element.parentNode) {
    if ((0, _element.hasClass)(element, 'colHeader')) {
      renderedIndex = parentOverlay.wtTable.columnFilter.sourceToRendered(index);
    } else if ((0, _element.hasClass)(element, 'rowHeader')) {
      renderedIndex = parentOverlay.wtTable.rowFilter.sourceToRendered(index);
    }
  }

  if (renderedIndex > -1) {
    (0, _element.fastInnerHTML)(element, content(index));
  } else {
    // workaround for https://github.com/handsontable/handsontable/issues/1946
    (0, _element.fastInnerText)(element, String.fromCharCode(160));
    (0, _element.addClass)(element, 'cornerHeader');
  }
};

/**
 * Given a element's left position relative to the viewport, returns maximum element width until the right
 * edge of the viewport (before scrollbar)
 *
 * @param {Number} leftOffset
 * @return {Number}
 */
TableView.prototype.maximumVisibleElementWidth = function (leftOffset) {
  var workspaceWidth = this.wt.wtViewport.getWorkspaceWidth();
  var maxWidth = workspaceWidth - leftOffset;
  return maxWidth > 0 ? maxWidth : 0;
};

/**
 * Given a element's top position relative to the viewport, returns maximum element height until the bottom
 * edge of the viewport (before scrollbar)
 *
 * @param {Number} topOffset
 * @return {Number}
 */
TableView.prototype.maximumVisibleElementHeight = function (topOffset) {
  var workspaceHeight = this.wt.wtViewport.getWorkspaceHeight();
  var maxHeight = workspaceHeight - topOffset;
  return maxHeight > 0 ? maxHeight : 0;
};

TableView.prototype.mainViewIsActive = function () {
  return this.wt === this.activeWt;
};

TableView.prototype.destroy = function () {
  this.wt.destroy();
  this.eventManager.destroy();
};

exports.default = TableView;

/***/ }),
/* 384 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


exports.__esModule = true;

var _createClass = 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); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

exports.parseDelay = parseDelay;

var _feature = __webpack_require__(34);

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

/**
 * @class Interval
 * @util
 */
var Interval = function () {
  _createClass(Interval, null, [{
    key: 'create',
    value: function create(func, delay) {
      return new Interval(func, delay);
    }
  }]);

  function Interval(func, delay) {
    var _this = this;

    _classCallCheck(this, Interval);

    /**
     * Animation frame request id.
     *
     * @type {Number}
     */
    this.timer = null;
    /**
     * Function to invoke repeatedly.
     *
     * @type {Function}
     */
    this.func = func;
    /**
     * Number of milliseconds that function should wait before next call.
     */
    this.delay = parseDelay(delay);
    /**
     * Flag which indicates if interval object was stopped.
     *
     * @type {Boolean}
     * @default true
     */
    this.stopped = true;
    /**
     * Interval time (in milliseconds) of the last callback call.
     *
     * @private
     * @type {Number}
     */
    this._then = null;
    /**
     * Bounded function `func`.
     *
     * @private
     * @type {Function}
     */
    this._callback = function () {
      return _this.__callback();
    };
  }

  /**
   * Start loop.
   *
   * @returns {Interval}
   */


  _createClass(Interval, [{
    key: 'start',
    value: function start() {
      if (this.stopped) {
        this._then = Date.now();
        this.stopped = false;
        this.timer = (0, _feature.requestAnimationFrame)(this._callback);
      }

      return this;
    }

    /**
     * Stop looping.
     *
     * @returns {Interval}
     */

  }, {
    key: 'stop',
    value: function stop() {
      if (!this.stopped) {
        this.stopped = true;
        (0, _feature.cancelAnimationFrame)(this.timer);
        this.timer = null;
      }

      return this;
    }

    /**
     * Loop callback, fired on every animation frame.
     *
     * @private
     */

  }, {
    key: '__callback',
    value: function __callback() {
      this.timer = (0, _feature.requestAnimationFrame)(this._callback);

      if (this.delay) {
        var now = Date.now();
        var elapsed = now - this._then;

        if (elapsed > this.delay) {
          this._then = now - elapsed % this.delay;
          this.func();
        }
      } else {
        this.func();
      }
    }
  }]);

  return Interval;
}();

exports.default = Interval;
function parseDelay(delay) {
  if (typeof delay === 'string' && /fps$/.test(delay)) {
    delay = 1000 / parseInt(delay.replace('fps', '') || 0, 10);
  }

  return delay;
}

/***/ }),
/* 385 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


exports.__esModule = true;
exports.default = autocompleteValidator;
/**
 * Autocomplete cell validator.
 *
 * @private
 * @validator AutocompleteValidator
 * @param {*} value - Value of edited cell
 * @param {Function} callback - Callback called with validation result
 */
function autocompleteValidator(value, callback) {
  if (value == null) {
    value = '';
  }

  if (this.allowEmpty && value === '') {
    callback(true);

    return;
  }

  if (this.strict && this.source) {
    if (typeof this.source === 'function') {
      this.source(value, process(value, callback));
    } else {
      process(value, callback)(this.source);
    }
  } else {
    callback(true);
  }
};

/**
 * Function responsible for validation of autocomplete value.
 *
 * @param {*} value - Value of edited cell
 * @param {Function} callback - Callback called with validation result
 */
function process(value, callback) {
  var originalVal = value;

  return function (source) {
    var found = false;

    for (var s = 0, slen = source.length; s < slen; s++) {
      if (originalVal === source[s]) {
        found = true; // perfect match
        break;
      }
    }

    callback(found);
  };
}

/***/ }),
/* 386 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


exports.__esModule = true;
exports.default = dateValidator;
exports.correctFormat = correctFormat;

var _moment = __webpack_require__(42);

var _moment2 = _interopRequireDefault(_moment);

var _date = __webpack_require__(89);

var _editors = __webpack_require__(13);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

/**
 * Date cell validator
 *
 * @private
 * @validator DateValidator
 * @dependencies moment
 * @param {*} value - Value of edited cell
 * @param {Function} callback - Callback called with validation result
 */
function dateValidator(value, callback) {
  var valid = true;
  var dateEditor = (0, _editors.getEditorInstance)('date', this.instance);

  if (value == null) {
    value = '';
  }
  var isValidDate = (0, _moment2.default)(new Date(value)).isValid() || (0, _moment2.default)(value, dateEditor.defaultDateFormat).isValid();
  // is it in the specified format
  var isValidFormat = (0, _moment2.default)(value, this.dateFormat || dateEditor.defaultDateFormat, true).isValid();

  if (this.allowEmpty && value === '') {
    isValidDate = true;
    isValidFormat = true;
  }
  if (!isValidDate) {
    valid = false;
  }
  if (!isValidDate && isValidFormat) {
    valid = true;
  }

  if (isValidDate && !isValidFormat) {
    if (this.correctFormat === true) {
      // if format correction is enabled
      var correctedValue = correctFormat(value, this.dateFormat);
      var row = this.instance.runHooks('unmodifyRow', this.row);
      var column = this.instance.runHooks('unmodifyCol', this.col);

      this.instance.setDataAtCell(row, column, correctedValue, 'dateValidator');
      valid = true;
    } else {
      valid = false;
    }
  }

  callback(valid);
};

/**
 * Format the given string using moment.js' format feature
 *
 * @param {String} value
 * @param {String} dateFormat
 * @returns {String}
 */
function correctFormat(value, dateFormat) {
  var dateFromDate = (0, _moment2.default)((0, _date.getNormalizedDate)(value));
  var dateFromMoment = (0, _moment2.default)(value, dateFormat);
  var isAlphanumeric = value.search(/[A-z]/g) > -1;
  var date = void 0;

  if (dateFromDate.isValid() && dateFromDate.format('x') === dateFromMoment.format('x') || !dateFromMoment.isValid() || isAlphanumeric) {
    date = dateFromDate;
  } else {
    date = dateFromMoment;
  }

  return date.format(dateFormat);
};

/***/ }),
/* 387 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


exports.__esModule = true;
exports.default = numericValidator;
/**
 * Numeric cell validator
 *
 * @private
 * @validator NumericValidator
 * @param {*} value - Value of edited cell
 * @param {*} callback - Callback called with validation result
 */
function numericValidator(value, callback) {
  if (value == null) {
    value = '';
  }
  if (this.allowEmpty && value === '') {
    callback(true);
  } else if (value === '') {
    callback(false);
  } else {
    callback(/^-?\d*(\.|,)?\d*$/.test(value));
  }
};

/***/ }),
/* 388 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


exports.__esModule = true;
exports.default = timeValidator;

var _moment = __webpack_require__(42);

var _moment2 = _interopRequireDefault(_moment);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

// Formats which are correctly parsed to time (supported by momentjs)
var STRICT_FORMATS = ['YYYY-MM-DDTHH:mm:ss.SSSZ', 'X', // Unix timestamp
'x' // Unix ms timestamp
];

/**
 * Time cell validator
 *
 * @private
 * @validator TimeValidator
 * @dependencies moment
 * @param {*} value - Value of edited cell
 * @param {Function} callback - Callback called with validation result
 */
function timeValidator(value, callback) {
  var valid = true;
  var timeFormat = this.timeFormat || 'h:mm:ss a';

  if (value === null) {
    value = '';
  }

  value = /^\d{3,}$/.test(value) ? parseInt(value, 10) : value;

  var twoDigitValue = /^\d{1,2}$/.test(value);

  if (twoDigitValue) {
    value += ':00';
  }

  var date = (0, _moment2.default)(value, STRICT_FORMATS, true).isValid() ? (0, _moment2.default)(value) : (0, _moment2.default)(value, timeFormat);
  var isValidTime = date.isValid();

  // is it in the specified format
  var isValidFormat = (0, _moment2.default)(value, timeFormat, true).isValid() && !twoDigitValue;

  if (this.allowEmpty && value === '') {
    isValidTime = true;
    isValidFormat = true;
  }
  if (!isValidTime) {
    valid = false;
  }
  if (!isValidTime && isValidFormat) {
    valid = true;
  }
  if (isValidTime && !isValidFormat) {
    if (this.correctFormat === true) {
      // if format correction is enabled
      var correctedValue = date.format(timeFormat);
      var row = this.instance.runHooks('unmodifyRow', this.row);
      var column = this.instance.runHooks('unmodifyCol', this.col);

      this.instance.setDataAtCell(row, column, correctedValue, 'timeValidator');
      valid = true;
    } else {
      valid = false;
    }
  }

  callback(valid);
};

/***/ }),
/* 389 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";
// 22.1.3.3 Array.prototype.copyWithin(target, start, end = this.length)

var toObject = __webpack_require__(40);
var toAbsoluteIndex = __webpack_require__(63);
var toLength = __webpack_require__(21);

module.exports = [].copyWithin || function copyWithin(target /* = 0 */, start /* = 0, end = @length */) {
  var O = toObject(this);
  var len = toLength(O.length);
  var to = toAbsoluteIndex(target, len);
  var from = toAbsoluteIndex(start, len);
  var end = arguments.length > 2 ? arguments[2] : undefined;
  var count = Math.min((end === undefined ? len : toAbsoluteIndex(end, len)) - from, len - to);
  var inc = 1;
  if (from < to && to < from + count) {
    inc = -1;
    from += count - 1;
    to += count - 1;
  }
  while (count-- > 0) {
    if (from in O) O[to] = O[from];
    else delete O[to];
    to += inc;
    from += inc;
  } return O;
};


/***/ }),
/* 390 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";
// 22.1.3.6 Array.prototype.fill(value, start = 0, end = this.length)

var toObject = __webpack_require__(40);
var toAbsoluteIndex = __webpack_require__(63);
var toLength = __webpack_require__(21);
module.exports = function fill(value /* , start = 0, end = @length */) {
  var O = toObject(this);
  var length = toLength(O.length);
  var aLen = arguments.length;
  var index = toAbsoluteIndex(aLen > 1 ? arguments[1] : undefined, length);
  var end = aLen > 2 ? arguments[2] : undefined;
  var endPos = end === undefined ? length : toAbsoluteIndex(end, length);
  while (endPos > index) O[index++] = value;
  return O;
};


/***/ }),
/* 391 */
/***/ (function(module, exports, __webpack_require__) {

var isObject = __webpack_require__(12);
var isArray = __webpack_require__(277);
var SPECIES = __webpack_require__(8)('species');

module.exports = function (original) {
  var C;
  if (isArray(original)) {
    C = original.constructor;
    // cross-realm fallback
    if (typeof C == 'function' && (C === Array || isArray(C.prototype))) C = undefined;
    if (isObject(C)) {
      C = C[SPECIES];
      if (C === null) C = undefined;
    }
  } return C === undefined ? Array : C;
};


/***/ }),
/* 392 */
/***/ (function(module, exports, __webpack_require__) {

// 9.4.2.3 ArraySpeciesCreate(originalArray, length)
var speciesConstructor = __webpack_require__(391);

module.exports = function (original, length) {
  return new (speciesConstructor(original))(length);
};


/***/ }),
/* 393 */
/***/ (function(module, exports, __webpack_require__) {

// all enumerable object keys, includes symbols
var getKeys = __webpack_require__(39);
var gOPS = __webpack_require__(61);
var pIE = __webpack_require__(48);
module.exports = function (it) {
  var result = getKeys(it);
  var getSymbols = gOPS.f;
  if (getSymbols) {
    var symbols = getSymbols(it);
    var isEnum = pIE.f;
    var i = 0;
    var key;
    while (symbols.length > i) if (isEnum.call(it, key = symbols[i++])) result.push(key);
  } return result;
};


/***/ }),
/* 394 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";

// 21.2.5.3 get RegExp.prototype.flags
var anObject = __webpack_require__(17);
module.exports = function () {
  var that = anObject(this);
  var result = '';
  if (that.global) result += 'g';
  if (that.ignoreCase) result += 'i';
  if (that.multiline) result += 'm';
  if (that.unicode) result += 'u';
  if (that.sticky) result += 'y';
  return result;
};


/***/ }),
/* 395 */
/***/ (function(module, exports, __webpack_require__) {

var isObject = __webpack_require__(12);
var setPrototypeOf = __webpack_require__(287).set;
module.exports = function (that, target, C) {
  var S = target.constructor;
  var P;
  if (S !== C && typeof S == 'function' && (P = S.prototype) !== C.prototype && isObject(P) && setPrototypeOf) {
    setPrototypeOf(that, P);
  } return that;
};


/***/ }),
/* 396 */
/***/ (function(module, exports) {

// fast apply, http://jsperf.lnkit.com/fast-apply/5
module.exports = function (fn, args, that) {
  var un = that === undefined;
  switch (args.length) {
    case 0: return un ? fn()
                      : fn.call(that);
    case 1: return un ? fn(args[0])
                      : fn.call(that, args[0]);
    case 2: return un ? fn(args[0], args[1])
                      : fn.call(that, args[0], args[1]);
    case 3: return un ? fn(args[0], args[1], args[2])
                      : fn.call(that, args[0], args[1], args[2]);
    case 4: return un ? fn(args[0], args[1], args[2], args[3])
                      : fn.call(that, args[0], args[1], args[2], args[3]);
  } return fn.apply(that, args);
};


/***/ }),
/* 397 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";

var create = __webpack_require__(80);
var descriptor = __webpack_require__(49);
var setToStringTag = __webpack_require__(50);
var IteratorPrototype = {};

// 25.1.2.1.1 %IteratorPrototype%[@@iterator]()
__webpack_require__(31)(IteratorPrototype, __webpack_require__(8)('iterator'), function () { return this; });

module.exports = function (Constructor, NAME, next) {
  Constructor.prototype = create(IteratorPrototype, { next: descriptor(1, next) });
  setToStringTag(Constructor, NAME + ' Iterator');
};


/***/ }),
/* 398 */
/***/ (function(module, exports, __webpack_require__) {

var global = __webpack_require__(10);
var macrotask = __webpack_require__(86).set;
var Observer = global.MutationObserver || global.WebKitMutationObserver;
var process = global.process;
var Promise = global.Promise;
var isNode = __webpack_require__(38)(process) == 'process';

module.exports = function () {
  var head, last, notify;

  var flush = function () {
    var parent, fn;
    if (isNode && (parent = process.domain)) parent.exit();
    while (head) {
      fn = head.fn;
      head = head.next;
      try {
        fn();
      } catch (e) {
        if (head) notify();
        else last = undefined;
        throw e;
      }
    } last = undefined;
    if (parent) parent.enter();
  };

  // Node.js
  if (isNode) {
    notify = function () {
      process.nextTick(flush);
    };
  // browsers with MutationObserver
  } else if (Observer) {
    var toggle = true;
    var node = document.createTextNode('');
    new Observer(flush).observe(node, { characterData: true }); // eslint-disable-line no-new
    notify = function () {
      node.data = toggle = !toggle;
    };
  // environments with maybe non-completely correct, but existent Promise
  } else if (Promise && Promise.resolve) {
    var promise = Promise.resolve();
    notify = function () {
      promise.then(flush);
    };
  // for other environments - macrotask based on:
  // - setImmediate
  // - MessageChannel
  // - window.postMessag
  // - onreadystatechange
  // - setTimeout
  } else {
    notify = function () {
      // strange IE + webpack dev server bug - use .call(global)
      macrotask.call(global, flush);
    };
  }

  return function (fn) {
    var task = { fn: fn, next: undefined };
    if (last) last.next = task;
    if (!head) {
      head = task;
      notify();
    } last = task;
  };
};


/***/ }),
/* 399 */
/***/ (function(module, exports, __webpack_require__) {

var dP = __webpack_require__(18);
var anObject = __webpack_require__(17);
var getKeys = __webpack_require__(39);

module.exports = __webpack_require__(20) ? Object.defineProperties : function defineProperties(O, Properties) {
  anObject(O);
  var keys = getKeys(Properties);
  var length = keys.length;
  var i = 0;
  var P;
  while (length > i) dP.f(O, P = keys[i++], Properties[P]);
  return O;
};


/***/ }),
/* 400 */
/***/ (function(module, exports, __webpack_require__) {

// fallback for IE11 buggy Object.getOwnPropertyNames with iframe and window
var toIObject = __webpack_require__(27);
var gOPN = __webpack_require__(82).f;
var toString = {}.toString;

var windowNames = typeof window == 'object' && window && Object.getOwnPropertyNames
  ? Object.getOwnPropertyNames(window) : [];

var getWindowNames = function (it) {
  try {
    return gOPN(it);
  } catch (e) {
    return windowNames.slice();
  }
};

module.exports.f = function getOwnPropertyNames(it) {
  return windowNames && toString.call(it) == '[object Window]' ? getWindowNames(it) : gOPN(toIObject(it));
};


/***/ }),
/* 401 */
/***/ (function(module, exports, __webpack_require__) {

// 19.1.2.9 / 15.2.3.2 Object.getPrototypeOf(O)
var has = __webpack_require__(26);
var toObject = __webpack_require__(40);
var IE_PROTO = __webpack_require__(83)('IE_PROTO');
var ObjectProto = Object.prototype;

module.exports = Object.getPrototypeOf || function (O) {
  O = toObject(O);
  if (has(O, IE_PROTO)) return O[IE_PROTO];
  if (typeof O.constructor == 'function' && O instanceof O.constructor) {
    return O.constructor.prototype;
  } return O instanceof Object ? ObjectProto : null;
};


/***/ }),
/* 402 */
/***/ (function(module, exports, __webpack_require__) {

// all object keys, includes non-enumerable and symbols
var gOPN = __webpack_require__(82);
var gOPS = __webpack_require__(61);
var anObject = __webpack_require__(17);
var Reflect = __webpack_require__(10).Reflect;
module.exports = Reflect && Reflect.ownKeys || function ownKeys(it) {
  var keys = gOPN.f(anObject(it));
  var getSymbols = gOPS.f;
  return getSymbols ? keys.concat(getSymbols(it)) : keys;
};


/***/ }),
/* 403 */
/***/ (function(module, exports) {

module.exports = function (exec) {
  try {
    return { e: false, v: exec() };
  } catch (e) {
    return { e: true, v: e };
  }
};


/***/ }),
/* 404 */
/***/ (function(module, exports, __webpack_require__) {

var anObject = __webpack_require__(17);
var isObject = __webpack_require__(12);
var newPromiseCapability = __webpack_require__(283);

module.exports = function (C, x) {
  anObject(C);
  if (isObject(x) && x.constructor === C) return x;
  var promiseCapability = newPromiseCapability.f(C);
  var resolve = promiseCapability.resolve;
  resolve(x);
  return promiseCapability.promise;
};


/***/ }),
/* 405 */
/***/ (function(module, exports) {

// 7.2.9 SameValue(x, y)
module.exports = Object.is || function is(x, y) {
  // eslint-disable-next-line no-self-compare
  return x === y ? x !== 0 || 1 / x === 1 / y : x != x && y != y;
};


/***/ }),
/* 406 */
/***/ (function(module, exports, __webpack_require__) {

// 7.3.20 SpeciesConstructor(O, defaultConstructor)
var anObject = __webpack_require__(17);
var aFunction = __webpack_require__(54);
var SPECIES = __webpack_require__(8)('species');
module.exports = function (O, D) {
  var C = anObject(O).constructor;
  var S;
  return C === undefined || (S = anObject(C)[SPECIES]) == undefined ? D : aFunction(S);
};


/***/ }),
/* 407 */
/***/ (function(module, exports, __webpack_require__) {

var toInteger = __webpack_require__(64);
var defined = __webpack_require__(33);
// true  -> String#at
// false -> String#codePointAt
module.exports = function (TO_STRING) {
  return function (that, pos) {
    var s = String(defined(that));
    var i = toInteger(pos);
    var l = s.length;
    var a, b;
    if (i < 0 || i >= l) return TO_STRING ? '' : undefined;
    a = s.charCodeAt(i);
    return a < 0xd800 || a > 0xdbff || i + 1 === l || (b = s.charCodeAt(i + 1)) < 0xdc00 || b > 0xdfff
      ? TO_STRING ? s.charAt(i) : a
      : TO_STRING ? s.slice(i, i + 2) : (a - 0xd800 << 10) + (b - 0xdc00) + 0x10000;
  };
};


/***/ }),
/* 408 */
/***/ (function(module, exports, __webpack_require__) {

var global = __webpack_require__(10);
var core = __webpack_require__(45);
var LIBRARY = __webpack_require__(60);
var wksExt = __webpack_require__(291);
var defineProperty = __webpack_require__(18).f;
module.exports = function (name) {
  var $Symbol = core.Symbol || (core.Symbol = LIBRARY ? {} : global.Symbol || {});
  if (name.charAt(0) != '_' && !(name in $Symbol)) defineProperty($Symbol, name, { value: wksExt.f(name) });
};


/***/ }),
/* 409 */
/***/ (function(module, exports, __webpack_require__) {

var map = {
	"./af": 134,
	"./af.js": 134,
	"./ar": 141,
	"./ar-dz": 135,
	"./ar-dz.js": 135,
	"./ar-kw": 136,
	"./ar-kw.js": 136,
	"./ar-ly": 137,
	"./ar-ly.js": 137,
	"./ar-ma": 138,
	"./ar-ma.js": 138,
	"./ar-sa": 139,
	"./ar-sa.js": 139,
	"./ar-tn": 140,
	"./ar-tn.js": 140,
	"./ar.js": 141,
	"./az": 142,
	"./az.js": 142,
	"./be": 143,
	"./be.js": 143,
	"./bg": 144,
	"./bg.js": 144,
	"./bn": 145,
	"./bn.js": 145,
	"./bo": 146,
	"./bo.js": 146,
	"./br": 147,
	"./br.js": 147,
	"./bs": 148,
	"./bs.js": 148,
	"./ca": 149,
	"./ca.js": 149,
	"./cs": 150,
	"./cs.js": 150,
	"./cv": 151,
	"./cv.js": 151,
	"./cy": 152,
	"./cy.js": 152,
	"./da": 153,
	"./da.js": 153,
	"./de": 156,
	"./de-at": 154,
	"./de-at.js": 154,
	"./de-ch": 155,
	"./de-ch.js": 155,
	"./de.js": 156,
	"./dv": 157,
	"./dv.js": 157,
	"./el": 158,
	"./el.js": 158,
	"./en-au": 159,
	"./en-au.js": 159,
	"./en-ca": 160,
	"./en-ca.js": 160,
	"./en-gb": 161,
	"./en-gb.js": 161,
	"./en-ie": 162,
	"./en-ie.js": 162,
	"./en-nz": 163,
	"./en-nz.js": 163,
	"./eo": 164,
	"./eo.js": 164,
	"./es": 166,
	"./es-do": 165,
	"./es-do.js": 165,
	"./es.js": 166,
	"./et": 167,
	"./et.js": 167,
	"./eu": 168,
	"./eu.js": 168,
	"./fa": 169,
	"./fa.js": 169,
	"./fi": 170,
	"./fi.js": 170,
	"./fo": 171,
	"./fo.js": 171,
	"./fr": 174,
	"./fr-ca": 172,
	"./fr-ca.js": 172,
	"./fr-ch": 173,
	"./fr-ch.js": 173,
	"./fr.js": 174,
	"./fy": 175,
	"./fy.js": 175,
	"./gd": 176,
	"./gd.js": 176,
	"./gl": 177,
	"./gl.js": 177,
	"./gom-latn": 178,
	"./gom-latn.js": 178,
	"./he": 179,
	"./he.js": 179,
	"./hi": 180,
	"./hi.js": 180,
	"./hr": 181,
	"./hr.js": 181,
	"./hu": 182,
	"./hu.js": 182,
	"./hy-am": 183,
	"./hy-am.js": 183,
	"./id": 184,
	"./id.js": 184,
	"./is": 185,
	"./is.js": 185,
	"./it": 186,
	"./it.js": 186,
	"./ja": 187,
	"./ja.js": 187,
	"./jv": 188,
	"./jv.js": 188,
	"./ka": 189,
	"./ka.js": 189,
	"./kk": 190,
	"./kk.js": 190,
	"./km": 191,
	"./km.js": 191,
	"./kn": 192,
	"./kn.js": 192,
	"./ko": 193,
	"./ko.js": 193,
	"./ky": 194,
	"./ky.js": 194,
	"./lb": 195,
	"./lb.js": 195,
	"./lo": 196,
	"./lo.js": 196,
	"./lt": 197,
	"./lt.js": 197,
	"./lv": 198,
	"./lv.js": 198,
	"./me": 199,
	"./me.js": 199,
	"./mi": 200,
	"./mi.js": 200,
	"./mk": 201,
	"./mk.js": 201,
	"./ml": 202,
	"./ml.js": 202,
	"./mr": 203,
	"./mr.js": 203,
	"./ms": 205,
	"./ms-my": 204,
	"./ms-my.js": 204,
	"./ms.js": 205,
	"./my": 206,
	"./my.js": 206,
	"./nb": 207,
	"./nb.js": 207,
	"./ne": 208,
	"./ne.js": 208,
	"./nl": 210,
	"./nl-be": 209,
	"./nl-be.js": 209,
	"./nl.js": 210,
	"./nn": 211,
	"./nn.js": 211,
	"./pa-in": 212,
	"./pa-in.js": 212,
	"./pl": 213,
	"./pl.js": 213,
	"./pt": 215,
	"./pt-br": 214,
	"./pt-br.js": 214,
	"./pt.js": 215,
	"./ro": 216,
	"./ro.js": 216,
	"./ru": 217,
	"./ru.js": 217,
	"./sd": 218,
	"./sd.js": 218,
	"./se": 219,
	"./se.js": 219,
	"./si": 220,
	"./si.js": 220,
	"./sk": 221,
	"./sk.js": 221,
	"./sl": 222,
	"./sl.js": 222,
	"./sq": 223,
	"./sq.js": 223,
	"./sr": 225,
	"./sr-cyrl": 224,
	"./sr-cyrl.js": 224,
	"./sr.js": 225,
	"./ss": 226,
	"./ss.js": 226,
	"./sv": 227,
	"./sv.js": 227,
	"./sw": 228,
	"./sw.js": 228,
	"./ta": 229,
	"./ta.js": 229,
	"./te": 230,
	"./te.js": 230,
	"./tet": 231,
	"./tet.js": 231,
	"./th": 232,
	"./th.js": 232,
	"./tl-ph": 233,
	"./tl-ph.js": 233,
	"./tlh": 234,
	"./tlh.js": 234,
	"./tr": 235,
	"./tr.js": 235,
	"./tzl": 236,
	"./tzl.js": 236,
	"./tzm": 238,
	"./tzm-latn": 237,
	"./tzm-latn.js": 237,
	"./tzm.js": 238,
	"./uk": 239,
	"./uk.js": 239,
	"./ur": 240,
	"./ur.js": 240,
	"./uz": 242,
	"./uz-latn": 241,
	"./uz-latn.js": 241,
	"./uz.js": 242,
	"./vi": 243,
	"./vi.js": 243,
	"./x-pseudo": 244,
	"./x-pseudo.js": 244,
	"./yo": 245,
	"./yo.js": 245,
	"./zh-cn": 246,
	"./zh-cn.js": 246,
	"./zh-hk": 247,
	"./zh-hk.js": 247,
	"./zh-tw": 248,
	"./zh-tw.js": 248
};
function webpackContext(req) {
	return __webpack_require__(webpackContextResolve(req));
};
function webpackContextResolve(req) {
	var id = map[req];
	if(!(id + 1)) // check for number or string
		throw new Error("Cannot find module '" + req + "'.");
	return id;
};
webpackContext.keys = function webpackContextKeys() {
	return Object.keys(map);
};
webpackContext.resolve = webpackContextResolve;
module.exports = webpackContext;
webpackContext.id = 409;

/***/ }),
/* 410 */
/***/ (function(module, exports, __webpack_require__) {

/*!
 * Pikaday
 *
 * Copyright © 2014 David Bushell | BSD & MIT license | https://github.com/dbushell/Pikaday
 */

(function (root, factory)
{
    'use strict';

    var moment;
    if (true) {
        // CommonJS module
        // Load moment.js as an optional dependency
        try { moment = __webpack_require__(42); } catch (e) {}
        module.exports = factory(moment);
    } else if (typeof define === 'function' && define.amd) {
        // AMD. Register as an anonymous module.
        define(function (req)
        {
            // Load moment.js as an optional dependency
            var id = 'moment';
            try { moment = req(id); } catch (e) {}
            return factory(moment);
        });
    } else {
        root.Pikaday = factory(root.moment);
    }
}(this, function (moment)
{
    'use strict';

    /**
     * feature detection and helper functions
     */
    var hasMoment = typeof moment === 'function',

    hasEventListeners = !!window.addEventListener,

    document = window.document,

    sto = window.setTimeout,

    addEvent = function(el, e, callback, capture)
    {
        if (hasEventListeners) {
            el.addEventListener(e, callback, !!capture);
        } else {
            el.attachEvent('on' + e, callback);
        }
    },

    removeEvent = function(el, e, callback, capture)
    {
        if (hasEventListeners) {
            el.removeEventListener(e, callback, !!capture);
        } else {
            el.detachEvent('on' + e, callback);
        }
    },

    fireEvent = function(el, eventName, data)
    {
        var ev;

        if (document.createEvent) {
            ev = document.createEvent('HTMLEvents');
            ev.initEvent(eventName, true, false);
            ev = extend(ev, data);
            el.dispatchEvent(ev);
        } else if (document.createEventObject) {
            ev = document.createEventObject();
            ev = extend(ev, data);
            el.fireEvent('on' + eventName, ev);
        }
    },

    trim = function(str)
    {
        return str.trim ? str.trim() : str.replace(/^\s+|\s+$/g,'');
    },

    hasClass = function(el, cn)
    {
        return (' ' + el.className + ' ').indexOf(' ' + cn + ' ') !== -1;
    },

    addClass = function(el, cn)
    {
        if (!hasClass(el, cn)) {
            el.className = (el.className === '') ? cn : el.className + ' ' + cn;
        }
    },

    removeClass = function(el, cn)
    {
        el.className = trim((' ' + el.className + ' ').replace(' ' + cn + ' ', ' '));
    },

    isArray = function(obj)
    {
        return (/Array/).test(Object.prototype.toString.call(obj));
    },

    isDate = function(obj)
    {
        return (/Date/).test(Object.prototype.toString.call(obj)) && !isNaN(obj.getTime());
    },

    isWeekend = function(date)
    {
        var day = date.getDay();
        return day === 0 || day === 6;
    },

    isLeapYear = function(year)
    {
        // solution by Matti Virkkunen: http://stackoverflow.com/a/4881951
        return year % 4 === 0 && year % 100 !== 0 || year % 400 === 0;
    },

    getDaysInMonth = function(year, month)
    {
        return [31, isLeapYear(year) ? 29 : 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][month];
    },

    setToStartOfDay = function(date)
    {
        if (isDate(date)) date.setHours(0,0,0,0);
    },

    compareDates = function(a,b)
    {
        // weak date comparison (use setToStartOfDay(date) to ensure correct result)
        return a.getTime() === b.getTime();
    },

    extend = function(to, from, overwrite)
    {
        var prop, hasProp;
        for (prop in from) {
            hasProp = to[prop] !== undefined;
            if (hasProp && typeof from[prop] === 'object' && from[prop] !== null && from[prop].nodeName === undefined) {
                if (isDate(from[prop])) {
                    if (overwrite) {
                        to[prop] = new Date(from[prop].getTime());
                    }
                }
                else if (isArray(from[prop])) {
                    if (overwrite) {
                        to[prop] = from[prop].slice(0);
                    }
                } else {
                    to[prop] = extend({}, from[prop], overwrite);
                }
            } else if (overwrite || !hasProp) {
                to[prop] = from[prop];
            }
        }
        return to;
    },

    adjustCalendar = function(calendar) {
        if (calendar.month < 0) {
            calendar.year -= Math.ceil(Math.abs(calendar.month)/12);
            calendar.month += 12;
        }
        if (calendar.month > 11) {
            calendar.year += Math.floor(Math.abs(calendar.month)/12);
            calendar.month -= 12;
        }
        return calendar;
    },

    /**
     * defaults and localisation
     */
    defaults = {

        // bind the picker to a form field
        field: null,

        // automatically show/hide the picker on `field` focus (default `true` if `field` is set)
        bound: undefined,

        // position of the datepicker, relative to the field (default to bottom & left)
        // ('bottom' & 'left' keywords are not used, 'top' & 'right' are modifier on the bottom/left position)
        position: 'bottom left',

        // automatically fit in the viewport even if it means repositioning from the position option
        reposition: true,

        // the default output format for `.toString()` and `field` value
        format: 'YYYY-MM-DD',

        // the initial date to view when first opened
        defaultDate: null,

        // make the `defaultDate` the initial selected value
        setDefaultDate: false,

        // first day of week (0: Sunday, 1: Monday etc)
        firstDay: 0,

        // the default flag for moment's strict date parsing
        formatStrict: false,

        // the minimum/earliest date that can be selected
        minDate: null,
        // the maximum/latest date that can be selected
        maxDate: null,

        // number of years either side, or array of upper/lower range
        yearRange: 10,

        // show week numbers at head of row
        showWeekNumber: false,

        // used internally (don't config outside)
        minYear: 0,
        maxYear: 9999,
        minMonth: undefined,
        maxMonth: undefined,

        startRange: null,
        endRange: null,

        isRTL: false,

        // Additional text to append to the year in the calendar title
        yearSuffix: '',

        // Render the month after year in the calendar title
        showMonthAfterYear: false,

        // Render days of the calendar grid that fall in the next or previous month
        showDaysInNextAndPreviousMonths: false,

        // how many months are visible
        numberOfMonths: 1,

        // when numberOfMonths is used, this will help you to choose where the main calendar will be (default `left`, can be set to `right`)
        // only used for the first display or when a selected date is not visible
        mainCalendar: 'left',

        // Specify a DOM element to render the calendar in
        container: undefined,

        // internationalization
        i18n: {
            previousMonth : 'Previous Month',
            nextMonth     : 'Next Month',
            months        : ['January','February','March','April','May','June','July','August','September','October','November','December'],
            weekdays      : ['Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday'],
            weekdaysShort : ['Sun','Mon','Tue','Wed','Thu','Fri','Sat']
        },

        // Theme Classname
        theme: null,

        // callback function
        onSelect: null,
        onOpen: null,
        onClose: null,
        onDraw: null
    },


    /**
     * templating functions to abstract HTML rendering
     */
    renderDayName = function(opts, day, abbr)
    {
        day += opts.firstDay;
        while (day >= 7) {
            day -= 7;
        }
        return abbr ? opts.i18n.weekdaysShort[day] : opts.i18n.weekdays[day];
    },

    renderDay = function(opts)
    {
        var arr = [];
        var ariaSelected = 'false';
        if (opts.isEmpty) {
            if (opts.showDaysInNextAndPreviousMonths) {
                arr.push('is-outside-current-month');
            } else {
                return '<td class="is-empty"></td>';
            }
        }
        if (opts.isDisabled) {
            arr.push('is-disabled');
        }
        if (opts.isToday) {
            arr.push('is-today');
        }
        if (opts.isSelected) {
            arr.push('is-selected');
            ariaSelected = 'true';
        }
        if (opts.isInRange) {
            arr.push('is-inrange');
        }
        if (opts.isStartRange) {
            arr.push('is-startrange');
        }
        if (opts.isEndRange) {
            arr.push('is-endrange');
        }
        return '<td data-day="' + opts.day + '" class="' + arr.join(' ') + '" aria-selected="' + ariaSelected + '">' +
                 '<button class="pika-button pika-day" type="button" ' +
                    'data-pika-year="' + opts.year + '" data-pika-month="' + opts.month + '" data-pika-day="' + opts.day + '">' +
                        opts.day +
                 '</button>' +
               '</td>';
    },

    renderWeek = function (d, m, y) {
        // Lifted from http://javascript.about.com/library/blweekyear.htm, lightly modified.
        var onejan = new Date(y, 0, 1),
            weekNum = Math.ceil((((new Date(y, m, d) - onejan) / 86400000) + onejan.getDay()+1)/7);
        return '<td class="pika-week">' + weekNum + '</td>';
    },

    renderRow = function(days, isRTL)
    {
        return '<tr>' + (isRTL ? days.reverse() : days).join('') + '</tr>';
    },

    renderBody = function(rows)
    {
        return '<tbody>' + rows.join('') + '</tbody>';
    },

    renderHead = function(opts)
    {
        var i, arr = [];
        if (opts.showWeekNumber) {
            arr.push('<th></th>');
        }
        for (i = 0; i < 7; i++) {
            arr.push('<th scope="col"><abbr title="' + renderDayName(opts, i) + '">' + renderDayName(opts, i, true) + '</abbr></th>');
        }
        return '<thead><tr>' + (opts.isRTL ? arr.reverse() : arr).join('') + '</tr></thead>';
    },

    renderTitle = function(instance, c, year, month, refYear, randId)
    {
        var i, j, arr,
            opts = instance._o,
            isMinYear = year === opts.minYear,
            isMaxYear = year === opts.maxYear,
            html = '<div id="' + randId + '" class="pika-title" role="heading" aria-live="assertive">',
            monthHtml,
            yearHtml,
            prev = true,
            next = true;

        for (arr = [], i = 0; i < 12; i++) {
            arr.push('<option value="' + (year === refYear ? i - c : 12 + i - c) + '"' +
                (i === month ? ' selected="selected"': '') +
                ((isMinYear && i < opts.minMonth) || (isMaxYear && i > opts.maxMonth) ? 'disabled="disabled"' : '') + '>' +
                opts.i18n.months[i] + '</option>');
        }

        monthHtml = '<div class="pika-label">' + opts.i18n.months[month] + '<select class="pika-select pika-select-month" tabindex="-1">' + arr.join('') + '</select></div>';

        if (isArray(opts.yearRange)) {
            i = opts.yearRange[0];
            j = opts.yearRange[1] + 1;
        } else {
            i = year - opts.yearRange;
            j = 1 + year + opts.yearRange;
        }

        for (arr = []; i < j && i <= opts.maxYear; i++) {
            if (i >= opts.minYear) {
                arr.push('<option value="' + i + '"' + (i === year ? ' selected="selected"': '') + '>' + (i) + '</option>');
            }
        }
        yearHtml = '<div class="pika-label">' + year + opts.yearSuffix + '<select class="pika-select pika-select-year" tabindex="-1">' + arr.join('') + '</select></div>';

        if (opts.showMonthAfterYear) {
            html += yearHtml + monthHtml;
        } else {
            html += monthHtml + yearHtml;
        }

        if (isMinYear && (month === 0 || opts.minMonth >= month)) {
            prev = false;
        }

        if (isMaxYear && (month === 11 || opts.maxMonth <= month)) {
            next = false;
        }

        if (c === 0) {
            html += '<button class="pika-prev' + (prev ? '' : ' is-disabled') + '" type="button">' + opts.i18n.previousMonth + '</button>';
        }
        if (c === (instance._o.numberOfMonths - 1) ) {
            html += '<button class="pika-next' + (next ? '' : ' is-disabled') + '" type="button">' + opts.i18n.nextMonth + '</button>';
        }

        return html += '</div>';
    },

    renderTable = function(opts, data, randId)
    {
        return '<table cellpadding="0" cellspacing="0" class="pika-table" role="grid" aria-labelledby="' + randId + '">' + renderHead(opts) + renderBody(data) + '</table>';
    },


    /**
     * Pikaday constructor
     */
    Pikaday = function(options)
    {
        var self = this,
            opts = self.config(options);

        self._onMouseDown = function(e)
        {
            if (!self._v) {
                return;
            }
            e = e || window.event;
            var target = e.target || e.srcElement;
            if (!target) {
                return;
            }

            if (!hasClass(target, 'is-disabled')) {
                if (hasClass(target, 'pika-button') && !hasClass(target, 'is-empty') && !hasClass(target.parentNode, 'is-disabled')) {
                    self.setDate(new Date(target.getAttribute('data-pika-year'), target.getAttribute('data-pika-month'), target.getAttribute('data-pika-day')));
                    if (opts.bound) {
                        sto(function() {
                            self.hide();
                            if (opts.field) {
                                opts.field.blur();
                            }
                        }, 100);
                    }
                }
                else if (hasClass(target, 'pika-prev')) {
                    self.prevMonth();
                }
                else if (hasClass(target, 'pika-next')) {
                    self.nextMonth();
                }
            }
            if (!hasClass(target, 'pika-select')) {
                // if this is touch event prevent mouse events emulation
                if (e.preventDefault) {
                    e.preventDefault();
                } else {
                    e.returnValue = false;
                    return false;
                }
            } else {
                self._c = true;
            }
        };

        self._onChange = function(e)
        {
            e = e || window.event;
            var target = e.target || e.srcElement;
            if (!target) {
                return;
            }
            if (hasClass(target, 'pika-select-month')) {
                self.gotoMonth(target.value);
            }
            else if (hasClass(target, 'pika-select-year')) {
                self.gotoYear(target.value);
            }
        };

        self._onKeyChange = function(e)
        {
            e = e || window.event;

            if (self.isVisible()) {

                switch(e.keyCode){
                    case 13:
                    case 27:
                        opts.field.blur();
                        break;
                    case 37:
                        e.preventDefault();
                        self.adjustDate('subtract', 1);
                        break;
                    case 38:
                        self.adjustDate('subtract', 7);
                        break;
                    case 39:
                        self.adjustDate('add', 1);
                        break;
                    case 40:
                        self.adjustDate('add', 7);
                        break;
                }
            }
        };

        self._onInputChange = function(e)
        {
            var date;

            if (e.firedBy === self) {
                return;
            }
            if (hasMoment) {
                date = moment(opts.field.value, opts.format, opts.formatStrict);
                date = (date && date.isValid()) ? date.toDate() : null;
            }
            else {
                date = new Date(Date.parse(opts.field.value));
            }
            if (isDate(date)) {
              self.setDate(date);
            }
            if (!self._v) {
                self.show();
            }
        };

        self._onInputFocus = function()
        {
            self.show();
        };

        self._onInputClick = function()
        {
            self.show();
        };

        self._onInputBlur = function()
        {
            // IE allows pika div to gain focus; catch blur the input field
            var pEl = document.activeElement;
            do {
                if (hasClass(pEl, 'pika-single')) {
                    return;
                }
            }
            while ((pEl = pEl.parentNode));

            if (!self._c) {
                self._b = sto(function() {
                    self.hide();
                }, 50);
            }
            self._c = false;
        };

        self._onClick = function(e)
        {
            e = e || window.event;
            var target = e.target || e.srcElement,
                pEl = target;
            if (!target) {
                return;
            }
            if (!hasEventListeners && hasClass(target, 'pika-select')) {
                if (!target.onchange) {
                    target.setAttribute('onchange', 'return;');
                    addEvent(target, 'change', self._onChange);
                }
            }
            do {
                if (hasClass(pEl, 'pika-single') || pEl === opts.trigger) {
                    return;
                }
            }
            while ((pEl = pEl.parentNode));
            if (self._v && target !== opts.trigger && pEl !== opts.trigger) {
                self.hide();
            }
        };

        self.el = document.createElement('div');
        self.el.className = 'pika-single' + (opts.isRTL ? ' is-rtl' : '') + (opts.theme ? ' ' + opts.theme : '');

        addEvent(self.el, 'mousedown', self._onMouseDown, true);
        addEvent(self.el, 'touchend', self._onMouseDown, true);
        addEvent(self.el, 'change', self._onChange);
        addEvent(document, 'keydown', self._onKeyChange);

        if (opts.field) {
            if (opts.container) {
                opts.container.appendChild(self.el);
            } else if (opts.bound) {
                document.body.appendChild(self.el);
            } else {
                opts.field.parentNode.insertBefore(self.el, opts.field.nextSibling);
            }
            addEvent(opts.field, 'change', self._onInputChange);

            if (!opts.defaultDate) {
                if (hasMoment && opts.field.value) {
                    opts.defaultDate = moment(opts.field.value, opts.format).toDate();
                } else {
                    opts.defaultDate = new Date(Date.parse(opts.field.value));
                }
                opts.setDefaultDate = true;
            }
        }

        var defDate = opts.defaultDate;

        if (isDate(defDate)) {
            if (opts.setDefaultDate) {
                self.setDate(defDate, true);
            } else {
                self.gotoDate(defDate);
            }
        } else {
            self.gotoDate(new Date());
        }

        if (opts.bound) {
            this.hide();
            self.el.className += ' is-bound';
            addEvent(opts.trigger, 'click', self._onInputClick);
            addEvent(opts.trigger, 'focus', self._onInputFocus);
            addEvent(opts.trigger, 'blur', self._onInputBlur);
        } else {
            this.show();
        }
    };


    /**
     * public Pikaday API
     */
    Pikaday.prototype = {


        /**
         * configure functionality
         */
        config: function(options)
        {
            if (!this._o) {
                this._o = extend({}, defaults, true);
            }

            var opts = extend(this._o, options, true);

            opts.isRTL = !!opts.isRTL;

            opts.field = (opts.field && opts.field.nodeName) ? opts.field : null;

            opts.theme = (typeof opts.theme) === 'string' && opts.theme ? opts.theme : null;

            opts.bound = !!(opts.bound !== undefined ? opts.field && opts.bound : opts.field);

            opts.trigger = (opts.trigger && opts.trigger.nodeName) ? opts.trigger : opts.field;

            opts.disableWeekends = !!opts.disableWeekends;

            opts.disableDayFn = (typeof opts.disableDayFn) === 'function' ? opts.disableDayFn : null;

            var nom = parseInt(opts.numberOfMonths, 10) || 1;
            opts.numberOfMonths = nom > 4 ? 4 : nom;

            if (!isDate(opts.minDate)) {
                opts.minDate = false;
            }
            if (!isDate(opts.maxDate)) {
                opts.maxDate = false;
            }
            if ((opts.minDate && opts.maxDate) && opts.maxDate < opts.minDate) {
                opts.maxDate = opts.minDate = false;
            }
            if (opts.minDate) {
                this.setMinDate(opts.minDate);
            }
            if (opts.maxDate) {
                this.setMaxDate(opts.maxDate);
            }

            if (isArray(opts.yearRange)) {
                var fallback = new Date().getFullYear() - 10;
                opts.yearRange[0] = parseInt(opts.yearRange[0], 10) || fallback;
                opts.yearRange[1] = parseInt(opts.yearRange[1], 10) || fallback;
            } else {
                opts.yearRange = Math.abs(parseInt(opts.yearRange, 10)) || defaults.yearRange;
                if (opts.yearRange > 100) {
                    opts.yearRange = 100;
                }
            }

            return opts;
        },

        /**
         * return a formatted string of the current selection (using Moment.js if available)
         */
        toString: function(format)
        {
            return !isDate(this._d) ? '' : hasMoment ? moment(this._d).format(format || this._o.format) : this._d.toDateString();
        },

        /**
         * return a Moment.js object of the current selection (if available)
         */
        getMoment: function()
        {
            return hasMoment ? moment(this._d) : null;
        },

        /**
         * set the current selection from a Moment.js object (if available)
         */
        setMoment: function(date, preventOnSelect)
        {
            if (hasMoment && moment.isMoment(date)) {
                this.setDate(date.toDate(), preventOnSelect);
            }
        },

        /**
         * return a Date object of the current selection with fallback for the current date
         */
        getDate: function()
        {
            return isDate(this._d) ? new Date(this._d.getTime()) : new Date();
        },

        /**
         * set the current selection
         */
        setDate: function(date, preventOnSelect)
        {
            if (!date) {
                this._d = null;

                if (this._o.field) {
                    this._o.field.value = '';
                    fireEvent(this._o.field, 'change', { firedBy: this });
                }

                return this.draw();
            }
            if (typeof date === 'string') {
                date = new Date(Date.parse(date));
            }
            if (!isDate(date)) {
                return;
            }

            var min = this._o.minDate,
                max = this._o.maxDate;

            if (isDate(min) && date < min) {
                date = min;
            } else if (isDate(max) && date > max) {
                date = max;
            }

            this._d = new Date(date.getTime());
            setToStartOfDay(this._d);
            this.gotoDate(this._d);

            if (this._o.field) {
                this._o.field.value = this.toString();
                fireEvent(this._o.field, 'change', { firedBy: this });
            }
            if (!preventOnSelect && typeof this._o.onSelect === 'function') {
                this._o.onSelect.call(this, this.getDate());
            }
        },

        /**
         * change view to a specific date
         */
        gotoDate: function(date)
        {
            var newCalendar = true;

            if (!isDate(date)) {
                return;
            }

            if (this.calendars) {
                var firstVisibleDate = new Date(this.calendars[0].year, this.calendars[0].month, 1),
                    lastVisibleDate = new Date(this.calendars[this.calendars.length-1].year, this.calendars[this.calendars.length-1].month, 1),
                    visibleDate = date.getTime();
                // get the end of the month
                lastVisibleDate.setMonth(lastVisibleDate.getMonth()+1);
                lastVisibleDate.setDate(lastVisibleDate.getDate()-1);
                newCalendar = (visibleDate < firstVisibleDate.getTime() || lastVisibleDate.getTime() < visibleDate);
            }

            if (newCalendar) {
                this.calendars = [{
                    month: date.getMonth(),
                    year: date.getFullYear()
                }];
                if (this._o.mainCalendar === 'right') {
                    this.calendars[0].month += 1 - this._o.numberOfMonths;
                }
            }

            this.adjustCalendars();
        },

        adjustDate: function(sign, days) {

            var day = this.getDate();
            var difference = parseInt(days)*24*60*60*1000;

            var newDay;

            if (sign === 'add') {
                newDay = new Date(day.valueOf() + difference);
            } else if (sign === 'subtract') {
                newDay = new Date(day.valueOf() - difference);
            }

            if (hasMoment) {
                if (sign === 'add') {
                    newDay = moment(day).add(days, "days").toDate();
                } else if (sign === 'subtract') {
                    newDay = moment(day).subtract(days, "days").toDate();
                }
            }

            this.setDate(newDay);
        },

        adjustCalendars: function() {
            this.calendars[0] = adjustCalendar(this.calendars[0]);
            for (var c = 1; c < this._o.numberOfMonths; c++) {
                this.calendars[c] = adjustCalendar({
                    month: this.calendars[0].month + c,
                    year: this.calendars[0].year
                });
            }
            this.draw();
        },

        gotoToday: function()
        {
            this.gotoDate(new Date());
        },

        /**
         * change view to a specific month (zero-index, e.g. 0: January)
         */
        gotoMonth: function(month)
        {
            if (!isNaN(month)) {
                this.calendars[0].month = parseInt(month, 10);
                this.adjustCalendars();
            }
        },

        nextMonth: function()
        {
            this.calendars[0].month++;
            this.adjustCalendars();
        },

        prevMonth: function()
        {
            this.calendars[0].month--;
            this.adjustCalendars();
        },

        /**
         * change view to a specific full year (e.g. "2012")
         */
        gotoYear: function(year)
        {
            if (!isNaN(year)) {
                this.calendars[0].year = parseInt(year, 10);
                this.adjustCalendars();
            }
        },

        /**
         * change the minDate
         */
        setMinDate: function(value)
        {
            if(value instanceof Date) {
                setToStartOfDay(value);
                this._o.minDate = value;
                this._o.minYear  = value.getFullYear();
                this._o.minMonth = value.getMonth();
            } else {
                this._o.minDate = defaults.minDate;
                this._o.minYear  = defaults.minYear;
                this._o.minMonth = defaults.minMonth;
                this._o.startRange = defaults.startRange;
            }

            this.draw();
        },

        /**
         * change the maxDate
         */
        setMaxDate: function(value)
        {
            if(value instanceof Date) {
                setToStartOfDay(value);
                this._o.maxDate = value;
                this._o.maxYear = value.getFullYear();
                this._o.maxMonth = value.getMonth();
            } else {
                this._o.maxDate = defaults.maxDate;
                this._o.maxYear = defaults.maxYear;
                this._o.maxMonth = defaults.maxMonth;
                this._o.endRange = defaults.endRange;
            }

            this.draw();
        },

        setStartRange: function(value)
        {
            this._o.startRange = value;
        },

        setEndRange: function(value)
        {
            this._o.endRange = value;
        },

        /**
         * refresh the HTML
         */
        draw: function(force)
        {
            if (!this._v && !force) {
                return;
            }
            var opts = this._o,
                minYear = opts.minYear,
                maxYear = opts.maxYear,
                minMonth = opts.minMonth,
                maxMonth = opts.maxMonth,
                html = '',
                randId;

            if (this._y <= minYear) {
                this._y = minYear;
                if (!isNaN(minMonth) && this._m < minMonth) {
                    this._m = minMonth;
                }
            }
            if (this._y >= maxYear) {
                this._y = maxYear;
                if (!isNaN(maxMonth) && this._m > maxMonth) {
                    this._m = maxMonth;
                }
            }

            randId = 'pika-title-' + Math.random().toString(36).replace(/[^a-z]+/g, '').substr(0, 2);

            for (var c = 0; c < opts.numberOfMonths; c++) {
                html += '<div class="pika-lendar">' + renderTitle(this, c, this.calendars[c].year, this.calendars[c].month, this.calendars[0].year, randId) + this.render(this.calendars[c].year, this.calendars[c].month, randId) + '</div>';
            }

            this.el.innerHTML = html;

            if (opts.bound) {
                if(opts.field.type !== 'hidden') {
                    sto(function() {
                        opts.trigger.focus();
                    }, 1);
                }
            }

            if (typeof this._o.onDraw === 'function') {
                this._o.onDraw(this);
            }
            
            if (opts.bound) {
                // let the screen reader user know to use arrow keys
                opts.field.setAttribute('aria-label', 'Use the arrow keys to pick a date');
            }
        },

        adjustPosition: function()
        {
            var field, pEl, width, height, viewportWidth, viewportHeight, scrollTop, left, top, clientRect;

            if (this._o.container) return;

            this.el.style.position = 'absolute';

            field = this._o.trigger;
            pEl = field;
            width = this.el.offsetWidth;
            height = this.el.offsetHeight;
            viewportWidth = window.innerWidth || document.documentElement.clientWidth;
            viewportHeight = window.innerHeight || document.documentElement.clientHeight;
            scrollTop = window.pageYOffset || document.body.scrollTop || document.documentElement.scrollTop;

            if (typeof field.getBoundingClientRect === 'function') {
                clientRect = field.getBoundingClientRect();
                left = clientRect.left + window.pageXOffset;
                top = clientRect.bottom + window.pageYOffset;
            } else {
                left = pEl.offsetLeft;
                top  = pEl.offsetTop + pEl.offsetHeight;
                while((pEl = pEl.offsetParent)) {
                    left += pEl.offsetLeft;
                    top  += pEl.offsetTop;
                }
            }

            // default position is bottom & left
            if ((this._o.reposition && left + width > viewportWidth) ||
                (
                    this._o.position.indexOf('right') > -1 &&
                    left - width + field.offsetWidth > 0
                )
            ) {
                left = left - width + field.offsetWidth;
            }
            if ((this._o.reposition && top + height > viewportHeight + scrollTop) ||
                (
                    this._o.position.indexOf('top') > -1 &&
                    top - height - field.offsetHeight > 0
                )
            ) {
                top = top - height - field.offsetHeight;
            }

            this.el.style.left = left + 'px';
            this.el.style.top = top + 'px';
        },

        /**
         * render HTML for a particular month
         */
        render: function(year, month, randId)
        {
            var opts   = this._o,
                now    = new Date(),
                days   = getDaysInMonth(year, month),
                before = new Date(year, month, 1).getDay(),
                data   = [],
                row    = [];
            setToStartOfDay(now);
            if (opts.firstDay > 0) {
                before -= opts.firstDay;
                if (before < 0) {
                    before += 7;
                }
            }
            var previousMonth = month === 0 ? 11 : month - 1,
                nextMonth = month === 11 ? 0 : month + 1,
                yearOfPreviousMonth = month === 0 ? year - 1 : year,
                yearOfNextMonth = month === 11 ? year + 1 : year,
                daysInPreviousMonth = getDaysInMonth(yearOfPreviousMonth, previousMonth);
            var cells = days + before,
                after = cells;
            while(after > 7) {
                after -= 7;
            }
            cells += 7 - after;
            for (var i = 0, r = 0; i < cells; i++)
            {
                var day = new Date(year, month, 1 + (i - before)),
                    isSelected = isDate(this._d) ? compareDates(day, this._d) : false,
                    isToday = compareDates(day, now),
                    isEmpty = i < before || i >= (days + before),
                    dayNumber = 1 + (i - before),
                    monthNumber = month,
                    yearNumber = year,
                    isStartRange = opts.startRange && compareDates(opts.startRange, day),
                    isEndRange = opts.endRange && compareDates(opts.endRange, day),
                    isInRange = opts.startRange && opts.endRange && opts.startRange < day && day < opts.endRange,
                    isDisabled = (opts.minDate && day < opts.minDate) ||
                                 (opts.maxDate && day > opts.maxDate) ||
                                 (opts.disableWeekends && isWeekend(day)) ||
                                 (opts.disableDayFn && opts.disableDayFn(day));

                if (isEmpty) {
                    if (i < before) {
                        dayNumber = daysInPreviousMonth + dayNumber;
                        monthNumber = previousMonth;
                        yearNumber = yearOfPreviousMonth;
                    } else {
                        dayNumber = dayNumber - days;
                        monthNumber = nextMonth;
                        yearNumber = yearOfNextMonth;
                    }
                }

                var dayConfig = {
                        day: dayNumber,
                        month: monthNumber,
                        year: yearNumber,
                        isSelected: isSelected,
                        isToday: isToday,
                        isDisabled: isDisabled,
                        isEmpty: isEmpty,
                        isStartRange: isStartRange,
                        isEndRange: isEndRange,
                        isInRange: isInRange,
                        showDaysInNextAndPreviousMonths: opts.showDaysInNextAndPreviousMonths
                    };

                row.push(renderDay(dayConfig));

                if (++r === 7) {
                    if (opts.showWeekNumber) {
                        row.unshift(renderWeek(i - before, month, year));
                    }
                    data.push(renderRow(row, opts.isRTL));
                    row = [];
                    r = 0;
                }
            }
            return renderTable(opts, data, randId);
        },

        isVisible: function()
        {
            return this._v;
        },

        show: function()
        {
            if (!this.isVisible()) {
                removeClass(this.el, 'is-hidden');
                this._v = true;
                this.draw();
                if (this._o.bound) {
                    addEvent(document, 'click', this._onClick);
                    this.adjustPosition();
                }
                if (typeof this._o.onOpen === 'function') {
                    this._o.onOpen.call(this);
                }
            }
        },

        hide: function()
        {
            var v = this._v;
            if (v !== false) {
                if (this._o.bound) {
                    removeEvent(document, 'click', this._onClick);
                }
                this.el.style.position = 'static'; // reset
                this.el.style.left = 'auto';
                this.el.style.top = 'auto';
                addClass(this.el, 'is-hidden');
                this._v = false;
                if (v !== undefined && typeof this._o.onClose === 'function') {
                    this._o.onClose.call(this);
                }
            }
        },

        /**
         * GAME OVER
         */
        destroy: function()
        {
            this.hide();
            removeEvent(this.el, 'mousedown', this._onMouseDown, true);
            removeEvent(this.el, 'touchend', this._onMouseDown, true);
            removeEvent(this.el, 'change', this._onChange);
            if (this._o.field) {
                removeEvent(this._o.field, 'change', this._onInputChange);
                if (this._o.bound) {
                    removeEvent(this._o.trigger, 'click', this._onInputClick);
                    removeEvent(this._o.trigger, 'focus', this._onInputFocus);
                    removeEvent(this._o.trigger, 'blur', this._onInputBlur);
                }
            }
            if (this.el.parentNode) {
                this.el.parentNode.removeChild(this.el);
            }
        }

    };

    return Pikaday;

}));


/***/ })
/******/ ]);
});