canvas-datagrid
Version:
Canvas based data grid web component. Capable of displaying millions of contiguous hierarchical rows and columns without paging or loading, on a single canvas element.
1,041 lines (1,031 loc) • 351 kB
JavaScript
(function webpackUniversalModuleDefinition(root, factory) {
if(typeof exports === 'object' && typeof module === 'object')
module.exports = factory();
else if(typeof define === 'function' && define.amd)
define([], factory);
else if(typeof exports === 'object')
exports["canvasDatagrid"] = factory();
else
root["canvasDatagrid"] = factory();
})(window, 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;
/******/
/******/ // define getter function for harmony exports
/******/ __webpack_require__.d = function(exports, name, getter) {
/******/ if(!__webpack_require__.o(exports, name)) {
/******/ Object.defineProperty(exports, name, { enumerable: true, get: getter });
/******/ }
/******/ };
/******/
/******/ // define __esModule on exports
/******/ __webpack_require__.r = function(exports) {
/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
/******/ }
/******/ Object.defineProperty(exports, '__esModule', { value: true });
/******/ };
/******/
/******/ // create a fake namespace object
/******/ // mode & 1: value is a module id, require it
/******/ // mode & 2: merge all properties of value into the ns
/******/ // mode & 4: return value when already ns object
/******/ // mode & 8|1: behave like require
/******/ __webpack_require__.t = function(value, mode) {
/******/ if(mode & 1) value = __webpack_require__(value);
/******/ if(mode & 8) return value;
/******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;
/******/ var ns = Object.create(null);
/******/ __webpack_require__.r(ns);
/******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value });
/******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));
/******/ return ns;
/******/ };
/******/
/******/ // 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 = "./lib/main.js");
/******/ })
/************************************************************************/
/******/ ({
/***/ "./lib/component.js":
/*!**************************!*\
!*** ./lib/component.js ***!
\**************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/*jslint browser: true, unparam: true, todo: true*/
/*globals define: true, MutationObserver: false, requestAnimationFrame: false, performance: false, btoa: false*/
!(__WEBPACK_AMD_DEFINE_ARRAY__ = [__webpack_require__(/*! ./defaults */ "./lib/defaults.js")], __WEBPACK_AMD_DEFINE_RESULT__ = (function (defaults) {
'use strict';
return function () {
var typeMap, component = {};
component.dehyphenateProperty = function hyphenateProperty(prop) {
prop = prop.replace('--cdg-', '');
var p = '', nextLetterCap;
Array.prototype.forEach.call(prop, function (char) {
if (nextLetterCap) {
nextLetterCap = false;
p += char.toUpperCase();
return;
}
if (char === '-') {
nextLetterCap = true;
return;
}
p += char;
});
return p;
};
component.hyphenateProperty = function hyphenateProperty(prop, cust) {
var p = '';
Array.prototype.forEach.call(prop, function (char) {
if (char === char.toUpperCase()) {
p += '-' + char.toLowerCase();
return;
}
p += char;
});
return (cust ? '--cdg-' : '') + p;
};
function getDefaultItem(base, item) {
var i = {},
r;
defaults(i);
r = i.defaults[base].filter(function (i) {
return i[0].toLowerCase() === item.toLowerCase()
|| component.hyphenateProperty(i[0]) === item.toLowerCase()
|| component.hyphenateProperty(i[0], true) === item.toLowerCase();
})[0];
return r;
}
component.applyComponentStyle = function (supressChangeAndDrawEvents, intf) {
if (!intf.isComponent) { return; }
var cStyle = window.getComputedStyle(intf.tagName === 'CANVAS-DATAGRID' ? intf : intf.canvas, null),
defs = {};
intf.computedStyle = cStyle;
defaults(defs);
defs = defs.defaults.styles;
defs.forEach(function (def) {
var val;
val = cStyle.getPropertyValue(component.hyphenateProperty(def[0], true));
if (val === "") {
val = cStyle.getPropertyValue(component.hyphenateProperty(def[0], false));
}
if (val !== "" && typeof val === 'string') {
intf.setStyleProperty(def[0], typeMap[typeof def[1]](val
.replace(/^\s+/, '').replace(/\s+$/, ''), def[1]), true);
}
});
if (!supressChangeAndDrawEvents && intf.dispatchEvent) {
requestAnimationFrame(function () { intf.resize(true); });
intf.dispatchEvent('stylechanged', intf.style);
}
};
typeMap = {
data: function (strData) {
try {
return JSON.parse(strData);
} catch (e) {
throw new Error('Cannot read JSON data in canvas-datagrid data.');
}
},
schema: function (strSchema) {
try {
return JSON.parse(strSchema);
} catch (e) {
throw new Error('Cannot read JSON data in canvas-datagrid schema attribute.');
}
},
number: function (strNum, def) {
var n = parseInt(strNum, 10);
return isNaN(n) ? def : n;
},
boolean: function (strBool) {
return (/true/i).test(strBool);
},
string: function (str) {
return str;
}
};
component.getObservableAttributes = function () {
var i = {}, attrs = ['data', 'schema', 'style', 'className', 'name'];
defaults(i);
i.defaults.attributes.forEach(function (attr) {
attrs.push(attr[0].toLowerCase());
});
return attrs;
};
component.disconnectedCallback = function () {
this.connected = false;
};
component.connectedCallback = function () {
var intf = this;
intf.connected = true;
component.observe(intf);
component.applyComponentStyle(true, intf);
intf.resize(true);
};
component.adoptedCallback = function () {
this.resize();
};
component.attributeChangedCallback = function (attrName, oldVal, newVal) {
var tfn, intf = this, def;
if (attrName === 'style') {
component.applyComponentStyle(false, intf);
return;
}
if (attrName === 'data') {
if (intf.dataType === 'application/x-canvas-datagrid') {
intf.dataType = 'application/json+x-canvas-datagrid';
}
intf.args.data = newVal;
return;
}
if (attrName === 'schema') {
intf.args.schema = typeMap.schema(newVal);
return;
}
if (attrName === 'name') {
intf.name = newVal;
return;
}
if (attrName === 'class' || attrName === 'className') {
return;
}
def = getDefaultItem('attributes', attrName);
if (def) {
tfn = typeMap[typeof def[1]];
intf.attributes[def[0]] = tfn(newVal);
return;
}
if (/^on/.test(attrName)) {
intf.addEventListener('on' + attrName, function (e) {
eval(newVal);
});
}
return;
};
component.observe = function (intf) {
var observer;
if (!window.MutationObserver) { return; }
intf.applyComponentStyle = function () { component.applyComponentStyle(false, intf); intf.resize(); };
/**
* Applies the computed css styles to the grid. In some browsers, changing directives in attached style sheets does not automatically update the styles in this component. It is necessary to call this method to update in these cases.
* @memberof canvasDatagrid
* @name applyComponentStyle
* @method
*/
observer = new window.MutationObserver(function (mutations) {
var checkInnerHTML, checkStyle;
Array.prototype.forEach.call(mutations, function (mutation) {
if (mutation.attributeName === 'class'
|| mutation.attributeName === 'style') {
checkStyle = true;
return;
}
if (mutation.target.parentNode
&& mutation.target.parentNode.nodeName === 'STYLE') {
checkStyle = true;
return;
}
if (mutation.addedNodes.length > 0 || mutation.type === 'characterData') {
checkInnerHTML = true;
}
});
if (checkStyle) {
intf.applyComponentStyle(false, intf);
}
if (checkInnerHTML) {
if (intf.dataType === 'application/x-canvas-datagrid') {
intf.dataType = 'application/json+x-canvas-datagrid';
}
intf.data = intf.innerHTML;
}
});
observer.observe(intf, { characterData: true, childList: true, attributes: true, subtree: true });
Array.prototype.forEach.call(document.querySelectorAll('style'), function (el) {
observer.observe(el, { characterData: true, childList: true, attributes: true, subtree: true });
});
};
return component;
};
}).apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),
__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
/***/ }),
/***/ "./lib/contextMenu.js":
/*!****************************!*\
!*** ./lib/contextMenu.js ***!
\****************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/*jslint browser: true, unparam: true, todo: true*/
/*globals define: true, MutationObserver: false, requestAnimationFrame: false, performance: false, btoa: false, Event: false*/
!(__WEBPACK_AMD_DEFINE_ARRAY__ = [], __WEBPACK_AMD_DEFINE_RESULT__ = (function () {
'use strict';
return function (self) {
var zIndexTop, hoverScrollTimeout, autoCompleteContext;
function applyContextItemStyle(contextItemContainer) {
self.createInlineStyle(contextItemContainer, 'canvas-datagrid-context-menu-item' + (self.mobile ? '-mobile' : ''));
contextItemContainer.addEventListener('mouseover', function () {
self.createInlineStyle(contextItemContainer, 'canvas-datagrid-context-menu-item:hover');
});
contextItemContainer.addEventListener('mouseout', function () {
self.createInlineStyle(contextItemContainer, 'canvas-datagrid-context-menu-item');
});
}
function createContextMenu(ev, pos, items, parentContextMenu) {
var container = document.createElement('div'),
upArrow = document.createElement('div'),
downArrow = document.createElement('div'),
children = [],
selectedIndex = -1,
intf = {},
rect;
if (!Array.isArray(items)) { throw new Error('createContextMenu expects an array.'); }
function createItems() {
items.forEach(function (item) {
var contextItemContainer = document.createElement('div'),
childMenuArrow;
function removeChildContext(e) {
if (e.relatedTarget === container
|| item.contextMenu.container === e.relatedTarget
|| childMenuArrow === e.relatedTarget
|| (contextItemContainer === e.relatedTarget)
|| item.contextMenu.container.contains(e.relatedTarget)
) { return; }
item.contextMenu.dispose();
children.splice(children.indexOf(item.contextMenu), 1);
item.contextMenu = undefined;
contextItemContainer.removeEventListener('mouseout', removeChildContext);
container.removeEventListener('mouseout', removeChildContext);
contextItemContainer.setAttribute('contextOpen', '0');
contextItemContainer.setAttribute('opening', '0');
}
function contextAddCallback(items) {
// check yet again if the user hasn't moved off
if (contextItemContainer.getAttribute('opening') !== '1' ||
contextItemContainer.getAttribute('contextOpen') === '1') {
return;
}
var cPos = contextItemContainer.getBoundingClientRect();
cPos = {
left: cPos.left + self.style.childContextMenuMarginLeft + container.offsetWidth,
top: cPos.top + self.style.childContextMenuMarginTop,
bottom: cPos.bottom,
right: cPos.right
};
item.contextMenu = createContextMenu(ev, cPos, items, intf);
contextItemContainer.setAttribute('contextOpen', '1');
contextItemContainer.addEventListener('mouseout', removeChildContext);
container.addEventListener('mouseout', removeChildContext);
children.push(item.contextMenu);
}
function createChildContext() {
var i;
if (contextItemContainer.getAttribute('contextOpen') === '1') {
return;
}
contextItemContainer.setAttribute('opening', '1');
if (typeof item.items === 'function') {
i = item.items.apply(intf, [function (items) {
contextAddCallback(items);
}]);
if (i !== undefined && Array.isArray(i)) {
contextAddCallback(i);
}
return;
}
contextAddCallback(item.items);
}
function addItem(item) {
function addContent(content) {
if (content === null) { return; }
if (typeof content === 'function') {
return addContent(content(ev));
}
if (typeof content === 'object') {
contextItemContainer.appendChild(content);
return;
}
applyContextItemStyle(contextItemContainer);
contextItemContainer.innerHTML = content;
return;
}
addContent(item.title);
item.contextItemContainer = contextItemContainer;
if ((item.items && item.items.length > 0) || typeof item.items === 'function') {
childMenuArrow = document.createElement('div');
self.createInlineStyle(childMenuArrow, 'canvas-datagrid-context-child-arrow');
childMenuArrow.innerHTML = self.style.childContextMenuArrowHTML;
contextItemContainer.appendChild(childMenuArrow);
contextItemContainer.addEventListener('mouseover', createChildContext);
contextItemContainer.addEventListener('mouseout', function () {
contextItemContainer.setAttribute('opening', '0');
});
}
if (item.click) {
contextItemContainer.addEventListener('click', function (ev) {
item.click.apply(self, [ev]);
});
}
}
addItem(item);
container.appendChild(contextItemContainer);
});
}
function clickIndex(idx) {
items[idx].contextItemContainer.dispatchEvent(new Event('click'));
}
function checkArrowVisibility() {
if (container.scrollTop > 0) {
self.parentDOMNode.appendChild(upArrow);
} else if (upArrow.parentNode) {
upArrow.parentNode.removeChild(upArrow);
}
if (container.scrollTop >= container.scrollHeight - container.offsetHeight && downArrow.parentNode) {
downArrow.parentNode.removeChild(downArrow);
} else if (container.scrollHeight - container.offsetHeight > 0
&& !(container.scrollTop >= container.scrollHeight - container.offsetHeight)) {
self.parentDOMNode.appendChild(downArrow);
}
}
function startHoverScroll(type) {
return function t() {
var a = self.attributes.contextHoverScrollAmount;
if (type === 'up' && container.scrollTop === 0) { return; }
if (type === 'down' && container.scrollTop === container.scrollHeight) { return; }
container.scrollTop += (type === 'up' ? -a : a);
hoverScrollTimeout = setTimeout(t, self.attributes.contextHoverScrollRateMs, type);
};
}
function endHoverScroll(type) {
return function () {
clearTimeout(hoverScrollTimeout);
};
}
function init() {
var loc = {},
s = self.scrollOffset(self.canvas);
if (zIndexTop === undefined) {
zIndexTop = self.style.contextMenuZIndex;
}
createItems();
self.createInlineStyle(container, 'canvas-datagrid-context-menu' + (self.mobile ? '-mobile' : ''));
loc.x = pos.left - s.left;
loc.y = pos.top - s.top;
loc.height = 0;
zIndexTop += 1;
container.style.position = 'absolute';
upArrow.style.color = self.style.contextMenuArrowColor;
downArrow.style.color = self.style.contextMenuArrowColor;
[upArrow, downArrow].forEach(function (el) {
el.style.textAlign = 'center';
el.style.position = 'absolute';
el.style.zIndex = zIndexTop + 1;
});
container.style.zIndex = zIndexTop;
if (parentContextMenu && parentContextMenu.inputDropdown) {
container.style.maxHeight = window.innerHeight - loc.y - self.style.autocompleteBottomMargin + 'px';
container.style.minWidth = pos.width + 'px';
loc.y += pos.height;
}
if (self.mobile) {
container.style.width = pos.width + 'px';
}
container.style.left = loc.x + 'px';
container.style.top = loc.y + 'px';
container.addEventListener('scroll', checkArrowVisibility);
container.addEventListener('wheel', function (e) {
if (self.hasFocus) {
container.scrollTop += e.deltaY;
container.scrollLeft += e.deltaX;
}
checkArrowVisibility();
});
upArrow.innerHTML = self.style.contextMenuArrowUpHTML;
downArrow.innerHTML = self.style.contextMenuArrowDownHTML;
container.appendChild(upArrow);
document.body.appendChild(downArrow);
document.body.appendChild(container);
rect = container.getBoundingClientRect();
// TODO: fix !(parentContextMenu && parentContextMenu.inputDropdown) state (autocomplete)
if (rect.bottom > window.innerHeight) {
if (!(parentContextMenu && parentContextMenu.inputDropdown)) {
loc.y -= (rect.bottom + self.style.contextMenuWindowMargin) - window.innerHeight;
}
if (loc.y < 0) { loc.y = self.style.contextMenuWindowMargin; }
if (container.offsetHeight > window.innerHeight - self.style.contextMenuWindowMargin) {
container.style.height = window.innerHeight - (self.style.contextMenuWindowMargin * 2) + 'px';
}
}
if (rect.right > window.innerWidth) {
loc.x -= rect.right - window.innerWidth + self.style.contextMenuWindowMargin;
}
if (loc.x < 0) { loc.x = self.style.contextMenuWindowMargin; }
if (loc.y < 0) { loc.y = self.style.contextMenuWindowMargin; }
container.style.left = loc.x + 'px';
container.style.top = loc.y + 'px';
rect = container.getBoundingClientRect();
upArrow.style.top = rect.top + 'px';
downArrow.style.top = rect.top + rect.height - downArrow.offsetHeight + 'px';
upArrow.style.left = rect.left + 'px';
downArrow.style.left = rect.left + 'px';
downArrow.style.width = container.offsetWidth + 'px';
upArrow.style.width = container.offsetWidth + 'px';
downArrow.addEventListener('mouseover', startHoverScroll('down'));
downArrow.addEventListener('mouseout', endHoverScroll('down'));
upArrow.addEventListener('mouseover', startHoverScroll('up'));
upArrow.addEventListener('mouseout', endHoverScroll('up'));
checkArrowVisibility();
}
intf.parentGrid = self.intf;
intf.parentContextMenu = parentContextMenu;
intf.container = container;
init();
intf.clickIndex = clickIndex;
intf.rect = rect;
intf.items = items;
intf.upArrow = upArrow;
intf.downArrow = downArrow;
intf.dispose = function () {
clearTimeout(hoverScrollTimeout);
children.forEach(function (c) {
c.dispose();
});
[downArrow, upArrow, container].forEach(function (el) {
if (el.parentNode) { el.parentNode.removeChild(el); }
});
};
Object.defineProperty(intf, 'selectedIndex', {
get: function () {
return selectedIndex;
},
set: function (value) {
if (typeof value !== 'number' || isNaN(value || !isFinite(value))) {
throw new Error('Context menu selected index must be a sane number.');
}
selectedIndex = value;
if (selectedIndex > items.length - 1) {
selectedIndex = items.length - 1;
}
if (selectedIndex < 0) {
selectedIndex = 0;
}
items.forEach(function (item, index) {
if (index === selectedIndex) {
return self.createInlineStyle(item.contextItemContainer, 'canvas-datagrid-context-menu-item:hover');
}
self.createInlineStyle(item.contextItemContainer, 'canvas-datagrid-context-menu-item');
});
}
});
return intf;
}
function createFilterContextMenuItems(e) {
var filterContainer = document.createElement('div'),
filterLabel = document.createElement('div'),
filterAutoCompleteButton = document.createElement('button'),
filterInput = document.createElement('input'),
n = e.cell && e.cell.header ? e.cell.header.title || e.cell.header.name : '',
autoCompleteItems,
iRect;
function checkRegExpErrorState() {
filterInput.style.background = self.style.contextFilterInputBackground;
filterInput.style.color = self.style.contextFilterInputColor;
if (self.invalidFilterRegEx) {
filterInput.style.background = self.style.contextFilterInvalidRegExpBackground;
filterInput.style.color = self.style.contextFilterInvalidRegExpColor;
}
}
function fillAutoComplete() {
var count = 0;
autoCompleteItems = {};
self.data.forEach(function (row) {
var value = row[e.cell.header.name];
if (autoCompleteItems[value] || count > self.attributes.maxAutoCompleteItems) { return; }
count += 1;
autoCompleteItems[value] = {
title: self.formatters[e.cell.header.type || 'string']({ cell: { value: value }}),
click: function (e) {
filterInput.value = value;
e.stopPropagation();
filterInput.dispatchEvent(new Event('keyup'));
self.disposeAutocomplete();
return;
}
};
});
autoCompleteItems = Object.keys(autoCompleteItems).map(function (key) {
return autoCompleteItems[key];
});
}
function createAutoCompleteContext(ev) {
if (ev && [40, 38, 13, 9].indexOf(ev.keyCode) !== -1) { return; }
fillAutoComplete();
iRect = filterInput.getBoundingClientRect();
if (autoCompleteContext) {
autoCompleteContext.dispose();
autoCompleteContext = undefined;
}
autoCompleteContext = createContextMenu(e, {
left: iRect.left,
top: iRect.top,
right: iRect.right,
bottom: iRect.bottom,
height: iRect.height,
width: iRect.width
}, autoCompleteItems, {inputDropdown: true});
autoCompleteContext.selectedIndex = 0;
}
self.createInlineStyle(filterLabel, 'canvas-datagrid-context-menu-label');
self.createInlineStyle(filterAutoCompleteButton, 'canvas-datagrid-context-menu-filter-button');
self.createInlineStyle(filterInput, 'canvas-datagrid-context-menu-filter-input');
checkRegExpErrorState();
filterInput.onclick = self.disposeAutocomplete;
filterInput.addEventListener('keydown', function (e) {
//down
if (e.keyCode === 40) {
autoCompleteContext.selectedIndex += 1;
}
//up
if (e.keyCode === 38) {
autoCompleteContext.selectedIndex -= 1;
}
//enter
if (e.keyCode === 13) {
autoCompleteContext.clickIndex(autoCompleteContext.selectedIndex);
self.disposeContextMenu();
}
//tab
if (e.keyCode === 9) {
autoCompleteContext.clickIndex(autoCompleteContext.selectedIndex);
e.preventDefault();
}
//esc
if (e.keyCode === 27) {
self.disposeContextMenu();
}
});
filterInput.addEventListener('keyup', function () {
self.setFilter(e.cell.header.name, filterInput.value);
});
filterInput.addEventListener('keyup', createAutoCompleteContext);
['focus', 'blur', 'keydown', 'keyup', 'change'].forEach(function (en) {
filterInput.addEventListener(en, checkRegExpErrorState);
});
filterInput.value = e.cell.header ? self.columnFilters[e.cell.header.name] || '' : '';
filterLabel.innerHTML = self.attributes.filterOptionText.replace(/%s/g, n);
filterAutoCompleteButton.onclick = function () {
if (autoCompleteContext) {
return self.disposeAutocomplete();
}
createAutoCompleteContext();
};
filterAutoCompleteButton.innerHTML = self.style.contextFilterButtonHTML;
filterContainer.addEventListener('click', function (e) {
return e.stopPropagation();
});
filterContainer.appendChild(filterLabel);
filterContainer.appendChild(filterInput);
filterContainer.appendChild(filterAutoCompleteButton);
e.items.push({
title: filterContainer
});
if (Object.keys(self.columnFilters).length) {
Object.keys(self.columnFilters).forEach(function (cf) {
var h = self.getHeaderByName(cf);
e.items.push({
title: self.attributes.removeFilterOptionText.replace(/%s/g, h.title || h.name),
click: function removeFilterClick(e) {
e.preventDefault();
self.setFilter(cf, '');
self.controlInput.focus();
}
});
});
}
}
function addDefaultContextMenuItem(e) {
var isNormalCell = !(e.cell.isBackground || e.cell.isColumnHeaderCellCap
|| e.cell.isScrollBar || e.cell.isCorner || e.cell.isRowHeader)
&& e.cell.header;
if (self.attributes.showFilter && isNormalCell) {
createFilterContextMenuItems(e);
}
if (self.attributes.showCopy
&& self.selections.reduce(function (p, r) {
return p + r.length;
}, 0) > 0) {
e.items.push({
title: self.attributes.copyText,
click: function () {
document.execCommand('copy');
self.disposeContextMenu();
self.controlInput.focus();
}
});
}
if (self.attributes.showPaste && self.clipBoardData) {
e.items.push({
title: self.attributes.pasteText,
click: function () {
self.paste(self.clipBoardData, e.cell.columnIndex, e.cell.rowIndex);
self.draw();
}
});
}
if (self.attributes.showColumnSelector) {
e.items.push({
title: self.attributes.columnSelectorText,
items: function () {
var d = [];
self.getSchema().forEach(function (column) {
function toggleColumnVisibility(e) {
column.hidden = !column.hidden;
e.preventDefault();
self.stopPropagation(e);
self.disposeContextMenu();
self.resize(true);
self.setStorageData();
}
var el = document.createElement('div');
applyContextItemStyle(el);
el.addEventListener('touchstart', toggleColumnVisibility);
el.addEventListener('click', toggleColumnVisibility);
el.innerHTML = (column.hidden ? self.attributes.columnSelectorHiddenText
: self.attributes.columnSelectorVisibleText)
+ (column.title || column.name);
d.push({
title: el
});
});
return d;
}
});
if (e.cell && e.cell.header && e.cell.columnIndex > -1) {
e.items.push({
title: self.attributes.hideColumnText
.replace(/%s/ig, e.cell.header.title || e.cell.header.name),
click: function (ev) {
self.getSchema()[e.cell.columnIndex].hidden = true;
ev.preventDefault();
self.stopPropagation(ev);
self.disposeContextMenu();
self.setStorageData();
setTimeout(function () { self.resize(true); }, 10);
}
});
}
}
if (self.attributes.saveAppearance && self.attributes.showClearSettingsOption
&& (Object.keys(self.sizes.rows).length > 0
|| Object.keys(self.sizes.columns).length > 0)) {
e.items.push({
title: self.attributes.clearSettingsOptionText,
click: function (e) {
e.preventDefault();
self.sizes.rows = {};
self.sizes.columns = {};
self.createRowOrders();
self.createColumnOrders();
self.storedSettings = undefined;
self.dispatchEvent('resizecolumn', {columnWidth: self.style.cellWidth});
self.dispatchEvent('resizerow', {cellHeight: self.style.cellHeight});
self.setStorageData();
self.resize(true);
self.disposeContextMenu();
self.controlInput.focus();
}
});
}
if (self.attributes.allowSorting && self.attributes.showOrderByOption && isNormalCell) {
e.items.push({
title: self.attributes.showOrderByOptionTextAsc.replace('%s', e.cell.header.title || e.cell.header.name),
click: function (ev) {
ev.preventDefault();
self.order(e.cell.header.name, 'asc');
self.controlInput.focus();
}
});
e.items.push({
title: self.attributes.showOrderByOptionTextDesc.replace('%s', e.cell.header.title || e.cell.header.name),
click: function (ev) {
ev.preventDefault();
self.order(e.cell.header.name, 'desc');
self.disposeContextMenu();
self.controlInput.focus();
}
});
}
}
self.disposeAutocomplete = function () {
if (autoCompleteContext) {
autoCompleteContext.dispose();
autoCompleteContext = undefined;
}
};
self.disposeContextMenu = function () {
document.removeEventListener('click', self.disposeContextMenu);
zIndexTop = self.style.contextMenuZIndex;
self.disposeAutocomplete();
if (self.contextMenu) {
self.contextMenu.dispose();
}
self.contextMenu = undefined;
};
self.contextmenuEvent = function (e, overridePos) {
if (!self.hasFocus && e.target !== self.canvas) {
return;
}
function createDiposeEvent() {
requestAnimationFrame(function () {
document.addEventListener('click', self.disposeContextMenu);
document.removeEventListener('mouseup', createDiposeEvent);
});
}
var contextPosition,
items = [],
pos = overridePos || self.getLayerPos(e),
ev = {
NativeEvent: e,
cell: self.getCellAt(pos.x, pos.y),
items: items
};
if (!ev.cell.isGrid) {
addDefaultContextMenuItem(ev);
}
if (self.dispatchEvent('contextmenu', ev)) {
return;
}
if (!ev.cell.isGrid) {
if (self.contextMenu) {
self.disposeContextMenu();
}
contextPosition = {
left: pos.x + pos.rect.left
+ self.style.contextMenuMarginLeft + self.canvasOffsetLeft,
top: pos.y + pos.rect.top
+ self.style.contextMenuMarginTop + self.canvasOffsetTop,
right: ev.cell.width + ev.cell.x + pos.rect.left,
bottom: ev.cell.height + ev.cell.y + pos.rect.top,
height: ev.cell.height,
width: ev.cell.width
};
if (self.mobile) {
contextPosition.left = self.style.mobileContextMenuMargin + 'px';
contextPosition.width = self.width - (self.style.mobileContextMenuMargin * 2) + 'px';
}
self.contextMenu = createContextMenu(ev, contextPosition, items);
document.addEventListener('mouseup', createDiposeEvent);
e.preventDefault();
}
};
return;
};
}).apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),
__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
/***/ }),
/***/ "./lib/defaults.js":
/*!*************************!*\
!*** ./lib/defaults.js ***!
\*************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/*jslint browser: true, unparam: true, todo: true*/
/*globals define: true, MutationObserver: false, requestAnimationFrame: false, performance: false, btoa: false*/
!(__WEBPACK_AMD_DEFINE_ARRAY__ = [], __WEBPACK_AMD_DEFINE_RESULT__ = (function () {
'use strict';
return function (self) {
self.defaults = {
attributes: [
['allowColumnReordering', true],
['allowColumnResize', true],
['allowColumnResizeFromCell', false],
['allowFreezingRows', false],
['allowFreezingColumns', false],
['allowMovingSelection', true],
['allowRowHeaderResize', true],
['allowRowReordering', false],
['allowRowResize', true],
['allowRowResizeFromCell', false],
['allowSorting', true],
['autoGenerateSchema', false],
['autoResizeColumns', false],
['borderDragBehavior', 'none'],
['borderResizeZone', 10],
['clearSettingsOptionText', 'Clear saved settings'],
['columnHeaderClickBehavior', 'sort'],
['columnSelectorHiddenText', ' '],
['columnSelectorText', 'Add/Remove columns'],
['columnSelectorVisibleText', '\u2713'],
['contextHoverScrollAmount', 2],
['contextHoverScrollRateMs', 5],
['copyHeadersOnSelectAll', true],
['copyText', 'Copy'],
['debug', false],
['editable', true],
['ellipsisText', '...'],
['filterOptionText', 'Filter %s'],
['filterTextPrefix', '(filtered) '],
['globalRowResize', false],
['hideColumnText', 'Hide %s'],
['maxAutoCompleteItems', 200],
['multiLine', false],
['name', ''],
['pageUpDownOverlap', 1],
['pasteText', 'Paste'],
['persistantSelectionMode', false],
['removeFilterOptionText', 'Remove filter on %s'],
['reorderDeadZone', 3],
['resizeScrollZone', 20],
['rowGrabZoneSize', 5],
['saveAppearance', true],
['scrollAnimationPPSThreshold', 0.75],
['scrollPointerLock', false],
['scrollRepeatRate', 75],
['selectionFollowsActiveCell', false],
['selectionHandleBehavior', 'none'],
['selectionMode', 'cell'],
['selectionScrollIncrement', 20],
['selectionScrollZone', 20],
['showClearSettingsOption', true],
['showColumnHeaders', true],
['showColumnSelector', true],
['showCopy', false],
['showFilter', true],
['showNewRow', false],
['showOrderByOption', true],
['showOrderByOptionTextAsc', 'Order by %s ascending'],
['showOrderByOptionTextDesc', 'Order by %s descending'],
['showPaste', false],
['showPerformance', false],
['showRowHeaders', true],
['showRowNumbers', true],
['snapToRow', false],
['touchContextMenuTimeMs', 800],
['touchDeadZone', 3],
['touchEasingMethod', 'easeOutQuad'],
['touchReleaseAcceleration', 1000],
['touchReleaseAnimationDurationMs', 2000],
['touchScrollZone', 20],
['touchSelectHandleZone', 20],
['touchZoomSensitivity', 0.005],
['touchZoomMin', 0.5],
['touchZoomMax', 1.75],
['maxPixelRatio', 2],
['tree', false],
['treeHorizontalScroll', false]
],
styles: [
['activeCellBackgroundColor', 'rgba(255, 255, 255, 1)'],
['activeCellBorderColor', 'rgba(110, 168, 255, 1)'],
['activeCellBorderWidth', 1],
['activeCellColor', 'rgba(0, 0, 0, 1)'],
['activeCellFont', '16px sans-serif'],
['activeCellHoverBackgroundColor', 'rgba(255, 255, 255, 1)'],
['activeCellHorizontalAlignment', 'left'],
['activeCellHoverColor', 'rgba(0, 0, 0, 1)'],
['activeCellOverlayBorderColor', 'rgba(66, 133, 244, 1)'],
['activeCellOverlayBorderWidth', 1],
['activeCellPaddingBottom', 5],
['activeCellPaddingLeft', 5],
['activeCellPaddingRight', 5],
['activeCellPaddingTop', 5],
['activeCellSelectedBackgroundColor', 'rgba(236, 243, 255, 1)'],
['activeCellSelectedColor', 'rgba(0, 0, 0, 1)'],
['activeCellVerticalAlignment', 'center'],
['activeColumnHeaderCellBackgroundColor', 'rgba(225, 225, 225, 1)'],
['activeColumnHeaderCellColor', 'rgba(0, 0, 0, 1)'],
['activeRowHeaderCellBackgroundColor', 'rgba(225, 225, 225, 1)'],
['activeRowHeaderCellColor', 'rgba(0, 0, 0, 1)'],
['autocompleteBottomMargin', 60],
['autosizeHeaderCellPadding', 8],
['autosizePadding', 5],
['cellAutoResizePadding', 13],
['cellBackgroundColor', 'rgba(255, 255, 255, 1)'],
['cellBorderColor', 'rgba(195, 199, 202, 1)'],
['cellBorderWidth', 1],
['cellColor', 'rgba(0, 0, 0, 1)'],
['cellFont', '16px sans-serif'],
['cellGridHeight', 250],
['cellHeight', 24],
['cellHeightWithChildGrid', 150],
['cellHorizontalAlignment', 'left'],
['cellHoverBackgroundColor', 'rgba(255, 255, 255, 1)'],
['cellHoverColor', 'rgba(0, 0, 0, 1)'],
['cellPaddingBottom', 5],
['cellPaddingLeft', 5],
['cellPaddingRight', 5],
['cellPaddingTop', 5],
['cellSelectedBackgroundColor', 'rgba(236, 243, 255, 1)'],
['cellSelectedColor', 'rgba(0, 0, 0, 1)'],
['cellVerticalAlignment', 'center'],
['cellWidth', 250],
['cellWidthWithChildGrid', 250],
['cellWhiteSpace', 'nowrap'],
['cellLineHeight', 1],
['cellLineSpacing', 3],
['childContextMenuArrowColor', 'rgba(43, 48, 43, 1)'],
['childContextMenuArrowHTML', '►'],
['childContextMenuMarginLeft', -11],
['childContextMenuMarginTop', -6],
['columnHeaderCellBackgroundColor', 'rgba(240, 240, 240, 1)'],
['columnHeaderCellBorderColor', 'rgba(172, 172, 172, 1)'],
['columnHeaderCellBorderWidth', 1],
['columnHeaderCellCapBackgroundColor', 'rgba(240, 240, 240, 1)'],
['columnHeaderCellCapBorderColor', 'rgba(172, 172, 172, 1)'],
['columnHeaderCellCapBorderWidth', 1],
['columnHeaderCellColor', 'rgba(50, 50, 50, 1)'],
['columnHeaderCellFont', '16px sans-serif'],
['columnHeaderCellHeight', 25],
['columnHeaderCellHorizontalAlignment', 'left'],
['columnHeaderCellHoverBackgroundColor', 'rgba(235, 235, 235, 1)'],
['columnHeaderCellHoverColor', 'rgba(0, 0, 0, 1)'],