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,110 lines (1,101 loc) • 321 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();
})(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;
/******/
/******/ // 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 = 1);
/******/ })
/************************************************************************/
/******/ ([
/* 0 */
/*!*************************!*\
!*** ./lib/defaults.js ***!
\*************************/
/*! no static exports found */
/*! all exports used */
/***/ (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],
['autoResizeColumns', false],
['borderDragBehavior', 'none'],
['borderResizeZone', 10],
['clearSettingsOptionText', 'Clear saved settings'],
['columnHeaderClickBehavior', 'sort'],
['columnSelectorHiddenText', ' '],
['columnSelectorText', 'Add/Remove columns'],
['columnSelectorVisibleText', '\u2713'],
['contextHoverScrollAmount', 2],
['contextHoverScrollRateMs', 5],
['copyText', 'Copy'],
['debug', false],
['editable', true],
['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', true],
['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', 1],
['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)'],
['activeCellHoverColor', 'rgba(0, 0, 0, 1)'],
['activeCellOverlayBorderColor', 'rgba(66, 133, 244, 1)'],
['activeCellOverlayBorderWidth', 1],
['activeCellPaddingBottom', 5],
['activeCellPaddingLeft', 5],
['activeCellPaddingRight', 7],
['activeCellPaddingTop', 5],
['activeCellSelectedBackgroundColor', 'rgba(236, 243, 255, 1)'],
['activeCellSelectedColor', 'rgba(0, 0, 0, 1)'],
['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', 7],
['cellPaddingTop', 5],
['cellSelectedBackgroundColor', 'rgba(236, 243, 255, 1)'],
['cellSelectedColor', 'rgba(0, 0, 0, 1)'],
['cellVerticalAlignment', 'center'],
['cellWidth', 250],
['cellWidthWithChildGrid', 250],
['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],
['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)'],
['columnHeaderCellPaddingBottom', 5],
['columnHeaderCellPaddingLeft', 5],
['columnHeaderCellPaddingRight', 7],
['columnHeaderCellPaddingTop', 5],
['columnHeaderCellVerticalAlignment', 'center'],
['columnHeaderOrderByArrowBorderColor', 'rgba(195, 199, 202, 1)'],
['columnHeaderOrderByArrowBorderWidth', 1],
['columnHeaderOrderByArrowColor', 'rgba(155, 155, 155, 1)'],
['columnHeaderOrderByArrowHeight', 8],
['columnHeaderOrderByArrowMarginLeft', 0],
['columnHeaderOrderByArrowMarginRight', 5],
['columnHeaderOrderByArrowMarginTop', 6],
['columnHeaderOrderByArrowWidth', 13],
['contextFilterButtonBorder', 'solid 1px rgba(158, 163, 169, 1)'],
['contextFilterButtonBorderRadius', '3px'],
['contextFilterButtonHTML', '▼'],
['contextFilterInputBackground', 'rgba(255,255,255,1)'],
['contextFilterInputBorder', 'solid 1px rgba(158, 163, 169, 1)'],
['contextFilterInputBorderRadius', '0'],
['contextFilterInputColor', 'rgba(0,0,0,1)'],
['contextFilterInputFontFamily', 'sans-serif'],
['contextFilterInputFontSize', '14px'],
['contextFilterInvalidRegExpBackground', 'rgba(180, 6, 1, 1)'],
['contextFilterInvalidRegExpColor', 'rgba(255, 255, 255, 1)'],
['contextMenuArrowColor', 'rgba(43, 48, 43, 1)'],
['contextMenuArrowDownHTML', '▼'],
['contextMenuArrowUpHTML', '▲'],
['contextMenuBackground', 'rgba(240, 240, 240, 1)'],
['contextMenuBorder', 'solid 1px rgba(158, 163, 169, 1)'],
['contextMenuBorderRadius', '3px'],
['contextMenuChildArrowFontSize', '12px'],
['contextMenuColor', 'rgba(43, 48, 43, 1)'],
['contextMenuFilterButtonFontFamily', 'sans-serif'],
['contextMenuFilterButtonFontSize', '10px'],
['contextMenuFilterInvalidExpresion', 'rgba(237, 155, 156, 1)'],
['contextMenuFontFamily', 'sans-serif'],
['contextMenuFontSize', '16px'],
['contextMenuHoverBackground', 'rgba(182, 205, 250, 1)'],
['contextMenuHoverColor', 'rgba(43, 48, 153, 1)'],
['contextMenuItemBorderRadius', '3px'],
['contextMenuItemMargin', '2px'],
['contextMenuLabelDisplay', 'inline-block'],
['contextMenuLabelMargin', '0 3px 0 0'],
['contextMenuLabelMaxWidth', '700px'],
['contextMenuLabelMinWidth', '75px'],
['contextMenuMarginLeft', 3],
['contextMenuMarginTop', -3],
['contextMenuOpacity', '0.98'],
['contextMenuPadding', '2px'],
['contextMenuWindowMargin', 100],
['contextMenuZIndex', 10000],
['cornerCellBackgroundColor', 'rgba(240, 240, 240, 1)'],
['cornerCellBorderColor', 'rgba(202, 202, 202, 1)'],
['editCellBackgroundColor', 'white'],
['editCellBorder', 'solid 1px rgba(110, 168, 255, 1)'],
['editCellBoxShadow', '0 2px 5px rgba(0,0,0,0.4)'],
['editCellColor', 'black'],
['editCellFontFamily', 'sans-serif'],
['editCellFontSize', '16px'],
['editCellPaddingLeft', 4],
['editCellZIndex', 10000],
['frozenMarkerHoverColor', 'rgba(236, 243, 255, 1)'],
['frozenMarkerHoverBorderColor', 'rgba(110, 168, 255, 1)'],
['frozenMarkerActiveColor', 'rgba(236, 243, 255, 1)'],
['frozenMarkerActiveBorderColor', 'rgba(110, 168, 255, 1)'],
['frozenMarkerColor', 'rgba(222, 222, 222, 1)'],
['frozenMarkerBorderColor', 'rgba(168, 168, 168, 1)'],
['frozenMarkerBorderWidth', 1],
['frozenMarkerWidth', 2],
['gridBackgroundColor', 'rgba(240, 240, 240, 1)'],
['gridBorderCollapse', 'collapse'],
['gridBorderColor', 'rgba(202, 202, 202, 1)'],
['gridBorderWidth', 1],
['minColumnWidth', 45],
['minRowHeight', 24],
['mobileContextMenuMargin', 10],
['mobileEditInputHeight', 30],
['mobileEditFontFamily', 'sans-serif'],
['mobileEditFontSize', '16px'],
['moveOverlayBorderWidth', 1],
['moveOverlayBorderColor', 'rgba(66, 133, 244, 1)'],
['moveOverlayBorderSegments', '12, 7'],
['name', 'default'],
['reorderMarkerBackgroundColor', 'rgba(0, 0, 0, 0.1)'],
['reorderMarkerBorderColor', 'rgba(0, 0, 0, 0.2)'],
['reorderMarkerBorderWidth', 1.25],
['reorderMarkerIndexBorderColor', 'rgba(66, 133, 244, 1)'],
['reorderMarkerIndexBorderWidth', 2.75],
['rowHeaderCellBackgroundColor', 'rgba(240, 240, 240, 1)'],
['rowHeaderCellBorderColor', 'rgba(200, 200, 200, 1)'],
['rowHeaderCellBorderWidth', 1],
['rowHeaderCellColor', 'rgba(50, 50, 50, 1)'],
['rowHeaderCellFont', '16px sans-serif'],
['rowHeaderCellHeight', 25],
['rowHeaderCellHorizontalAlignment', 'left'],
['rowHeaderCellHoverBackgroundColor', 'rgba(235, 235, 235, 1)'],
['rowHeaderCellHoverColor', 'rgba(0, 0, 0, 1)'],
['rowHeaderCellPaddingBottom', 5],
['rowHeaderCellPaddingLeft', 5],
['rowHeaderCellPaddingRight', 5],
['rowHeaderCellPaddingTop', 5],
['rowHeaderCellSelectedBackgroundColor', 'rgba(217, 217, 217, 1)'],
['rowHeaderCellSelectedColor', 'rgba(50, 50, 50, 1)'],
['rowHeaderCellVerticalAlignment', 'center'],
['rowHeaderCellWidth', 57],
['scrollBarActiveColor', 'rgba(125, 125, 125, 1)'],
['scrollBarBackgroundColor', 'rgba(240, 240, 240, 1)'],
['scrollBarBorderColor', 'rgba(202, 202, 202, 1)'],
['scrollBarBorderWidth', 0.5],
['scrollBarBoxBorderRadius', 4.125],
['scrollBarBoxColor', 'rgba(192, 192, 192, 1)'],
['scrollBarBoxMargin', 2],
['scrollBarBoxMinSize', 15],
['scrollBarBoxWidth', 8],
['scrollBarCornerBackgroundColor', 'rgba(240, 240, 240, 1)'],
['scrollBarCornerBorderColor', 'rgba(202, 202, 202, 1)'],
['scrollBarWidth', 11],
['selectionHandleBorderColor', 'rgba(255, 255, 255, 1)'],
['selectionHandleBorderWidth', 1.5],
['selectionHandleColor', 'rgba(66, 133, 244, 1)'],
['selectionHandleSize', 8],
['selectionHandleType', 'square'],
['selectionOverlayBorderColor', 'rgba(66, 133, 244, 1)'],
['selectionOverlayBorderWidth', 1],
['treeArrowBorderColor', 'rgba(195, 199, 202, 1)'],
['treeArrowBorderWidth', 1],
['treeArrowClickRadius', 5],
['treeArrowColor', 'rgba(155, 155, 155, 1)'],
['treeArrowHeight', 8],
['treeArrowMarginLeft', 0],
['treeArrowMarginRight', 5],
['treeArrowMarginTop', 6],
['treeArrowWidth', 13],
['treeGridHeight', 250]
]
};
};
}.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),
__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
/***/ }),
/* 1 */
/*!*********************!*\
!*** ./lib/main.js ***!
\*********************/
/*! no static exports found */
/*! all exports used */
/***/ (function(module, exports, __webpack_require__) {
var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/*jslint browser: true, unparam: true, todo: true, evil: true*/
/*globals Reflect: false, HTMLElement: true, define: true, MutationObserver: false, requestAnimationFrame: false, performance: false, btoa: false*/
!(__WEBPACK_AMD_DEFINE_ARRAY__ = [
__webpack_require__(/*! ./component */ 2),
__webpack_require__(/*! ./defaults */ 0),
__webpack_require__(/*! ./draw */ 3),
__webpack_require__(/*! ./events */ 4),
__webpack_require__(/*! ./touch */ 5),
__webpack_require__(/*! ./intf */ 6),
__webpack_require__(/*! ./contextMenu */ 7),
__webpack_require__(/*! ./dom */ 8),
__webpack_require__(/*! ./publicMethods */ 9)
], __WEBPACK_AMD_DEFINE_RESULT__ = function context(component) {
'use strict';
component = component();
var modules = Array.prototype.slice.call(arguments);
function Grid(args) {
args = args || {};
var self = {};
self.isComponent = args.component === undefined;
self.isChildGrid = args.parentNode && /canvas-datagrid-(cell|tree)/.test(args.parentNode.nodeType);
if (self.isChildGrid) {
self.intf = {};
} else {
self.intf = self.isComponent ? eval('Reflect.construct(HTMLElement, [], new.target)')
: document.createElement('section');
}
self.args = args;
self.createGrid = function grid(args) {
args.component = false;
return new Grid(args);
};
modules.forEach(function (module) {
module(self);
});
if (self.isChildGrid) {
self.shadowRoot = args.parentNode.shadowRoot;
self.parentNode = args.parentNode;
} else if (self.intf.createShadowRoot) {
self.shadowRoot = self.intf.attachShadow({mode: self.args.debug ? 'open' : 'closed'});
self.parentNode = self.shadowRoot;
} else {
self.parentNode = self.intf;
}
self.init();
return self.intf;
}
if (window.HTMLElement) {
Grid.prototype = Object.create(window.HTMLElement.prototype);
}
// export web component
if (window.customElements) {
Grid.observedAttributes = component.getObservableAttributes();
Grid.prototype.disconnectedCallback = component.disconnectedCallback;
Grid.prototype.attributeChangedCallback = component.attributeChangedCallback;
Grid.prototype.connectedCallback = component.connectedCallback;
Grid.prototype.adoptedCallback = component.adoptedCallback;
window.customElements.define('canvas-datagrid', Grid);
}
// export global
if (window && !window.canvasDatagrid && !window.require) {
window.canvasDatagrid = function (args) { return new Grid(args); };
}
// export amd loader
module.exports = function grid(args) {
args = args || {};
var i, tKeys = ['style', 'schema', 'data', 'formatters',
'sorters', 'filters'];
if (window.customElements && document.body.createShadowRoot) {
i = document.createElement('canvas-datagrid');
// create "block" element effect
i.style.width = '100%';
i.style.height = '100%';
Object.keys(args).forEach(function (argKey) {
if (argKey === 'parentNode') {
args.parentNode.appendChild(i);
return;
}
// top level keys in args
if (tKeys.indexOf(argKey) !== -1) {
tKeys.forEach(function (tKey) {
if (args[tKey] === undefined || tKey !== argKey) { return; }
if (['formatters', 'sorters', 'filters'].indexOf(argKey) !== -1) {
if (typeof args[tKey] === 'object' && args[tKey] !== null) {
Object.keys(args[tKey]).forEach(function (sKey) {
i[tKey][sKey] = args[tKey][sKey];
});
}
} else {
i[tKey] = args[tKey];
}
});
return;
}
// all others are attribute level keys
i.attributes[argKey] = args[argKey];
});
return i;
}
args.component = false;
i = new Grid(args);
if (args.parentNode && args.parentNode.appendChild) {
args.parentNode.appendChild(i);
}
// create "block" element effect
i.style.width = '100%';
i.style.height = '100%';
return i;
};
return module.exports;
}.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),
__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
/***/ }),
/* 2 */
/*!**************************!*\
!*** ./lib/component.js ***!
\**************************/
/*! no static exports found */
/*! all exports used */
/***/ (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 */ 0)], __WEBPACK_AMD_DEFINE_RESULT__ = function (defaults) {
'use strict';
return function () {
var typeMap, component = {};
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()
|| hyphenateProperty(i[0]) === item.toLowerCase()
|| hyphenateProperty(i[0], true) === item.toLowerCase();
})[0];
return r;
}
function applyComponentStyle(supressChangeAndDrawEvents, intf) {
var cStyle = window.getComputedStyle(intf, null),
defs = {};
intf.computedStyle = cStyle;
defaults(defs);
defs = defs.defaults.styles;
defs.forEach(function (def) {
var val = cStyle.getPropertyValue(hyphenateProperty(def[0], true));
if (val === "") {
val = cStyle.getPropertyValue(hyphenateProperty(def[0], false));
}
if (val !== "") {
intf.setStyleProperty(def[0], typeMap[typeof def[1]](val, def[1]));
}
});
requestAnimationFrame(function () { intf.resize(true); });
if (!supressChangeAndDrawEvents && intf.dispatchEvent) {
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);
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') {
requestAnimationFrame(function () { applyComponentStyle(false, intf); });
return;
}
if (attrName === 'data') {
intf.args.data = typeMap.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 () { 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') {
intf.applyComponentStyle(false, intf);
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) {
intf.data = typeMap.data(intf.innerHTML);
}
});
observer.observe(intf, { characterData: true, childList: true, attributes: true, subtree: true });
observer.observe(intf.canvas, { attributes: 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__));
/***/ }),
/* 3 */
/*!*********************!*\
!*** ./lib/draw.js ***!
\*********************/
/*! no static exports found */
/*! all exports used */
/***/ (function(module, exports, __webpack_require__) {
var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/*jslint browser: true, unparam: true, todo: true*/
/*globals XMLSerializer: false, define: true, Blob: false, MutationObserver: false, requestAnimationFrame: false, performance: false, btoa: false*/
!(__WEBPACK_AMD_DEFINE_ARRAY__ = [], __WEBPACK_AMD_DEFINE_RESULT__ = function () {
'use strict';
return function (self) {
var perfCounters = [],
drawCount = 0,
perfWindowSize = 300,
entityCount = [],
scrollDebugCounters = [],
touchPPSCounters = [];
self.htmlImageCache = {};
function drawPerfLine(w, h, x, y, perfArr, arrIndex, max, color, useAbs) {
var i = w / perfArr.length,
r = h / max;
x += self.canvasOffsetLeft;
y += self.canvasOffsetTop;
self.ctx.beginPath();
self.ctx.moveTo(x, y + h);
perfArr.forEach(function (n) {
var val = (arrIndex === undefined ? n : n[arrIndex]),
cx,
cy;
if (useAbs) {
val = Math.abs(val);
}
cx = x + i;
cy = y + h - (val * r);
self.ctx.lineTo(cx, cy);
x += i;
});
self.ctx.moveTo(x + w, y + h);
self.ctx.strokeStyle = color;
self.ctx.stroke();
}
function drawOnAllImagesLoaded() {
var loaded = true;
Object.keys(self.htmlImageCache).forEach(function (html) {
if (!self.htmlImageCache[html].complete) {
loaded = false;
}
});
if (loaded) {
self.draw();
}
}
function drawHtml(cell) {
var img,
v = cell.innerHTML || cell.formattedValue,
x = cell.x + self.canvasOffsetLeft,
y = cell.y + self.canvasOffsetTop;
if (self.htmlImageCache[v]) {
img = self.htmlImageCache[v];
if (img.height !== cell.height || img.width !== cell.width) {
// height and width of the cell has changed, invalidate cache
self.htmlImageCache[v] = undefined;
} else {
if (!img.complete) {
return;
}
return self.ctx.drawImage(img, x, y);
}
}
img = new Image(cell.width, cell.height);
self.htmlImageCache[v] = img;
img.onload = function () {
self.ctx.drawImage(img, x, y);
drawOnAllImagesLoaded();
};
img.src = 'data:image/svg+xml;base64,' + btoa(
'<svg xmlns="http://www.w3.org/2000/svg" width="' + cell.width + '" height="' + cell.height + '">\n' +
'<foreignObject class="node" x="0" y="0" width="100%" height="100%">\n' +
'<body xmlns="http://www.w3.org/1999/xhtml" style="margin:0;padding:0;">\n' +
v + '\n' +
'</body>' +
'</foreignObject>\n' +
'</svg>\n'
);
}
function drawOrderByArrow(x, y) {
var mt = self.style.columnHeaderOrderByArrowMarginTop * self.scale,
ml = self.style.columnHeaderOrderByArrowMarginLeft * self.scale,
mr = self.style.columnHeaderOrderByArrowMarginRight * self.scale,
aw = self.style.columnHeaderOrderByArrowWidth * self.scale,
ah = self.style.columnHeaderOrderByArrowHeight * self.scale;
x += self.canvasOffsetLeft;
y += self.canvasOffsetTop;
self.ctx.fillStyle = self.style.columnHeaderOrderByArrowColor;
self.ctx.strokeStyle = self.style.columnHeaderOrderByArrowBorderColor;
self.ctx.beginPath();
x = x + ml;
y = y + mt;
if (self.orderDirection === 'asc') {
self.ctx.moveTo(x, y);
self.ctx.lineTo(x + aw, y);
self.ctx.lineTo(x + (aw * 0.5), y + ah);
self.ctx.moveTo(x, y);
} else {
self.ctx.lineTo(x, y + ah);
self.ctx.lineTo(x + aw, y + ah);
self.ctx.lineTo(x + (aw * 0.5), y);
self.ctx.lineTo(x, y + ah);
}
self.ctx.stroke();
self.ctx.fill();
return ml + aw + mr;
}
function drawTreeArrow(cell, x, y) {
var mt = self.style.treeArrowMarginTop * self.scale,
mr = self.style.treeArrowMarginRight * self.scale,
ml = self.style.treeArrowMarginLeft * self.scale,
aw = self.style.treeArrowWidth * self.scale,
ah = self.style.treeArrowHeight * self.scale;
x += self.canvasOffsetLeft;
y += self.canvasOffsetTop;
self.ctx.fillStyle = self.style.treeArrowColor;
self.ctx.strokeStyle = self.style.treeArrowBorderColor;
self.ctx.beginPath();
x = x + ml;
y = y + mt;
if (self.openChildren[cell.data[self.uniqueId]]) {
self.ctx.moveTo(x, y);
self.ctx.lineTo(x + aw, y);
self.ctx.lineTo(x + (aw * 0.5), y + ah);
self.ctx.moveTo(x, y);
} else {
self.ctx.lineTo(x, y);
self.ctx.lineTo(x + ah, y + (aw * 0.5));
self.ctx.lineTo(x, y + aw);
self.ctx.lineTo(x, y);
}
self.ctx.stroke();
self.ctx.fill();
return ml + aw + mr;
}
function radiusRect(x, y, w, h, radius) {
x += self.canvasOffsetLeft;
y += self.canvasOffsetTop;
var r = x + w, b = y + h;
self.ctx.beginPath();
self.ctx.moveTo(x + radius, y);
self.ctx.lineTo(r - radius, y);
self.ctx.quadraticCurveTo(r, y, r, y + radius);
self.ctx.lineTo(r, y + h - radius);
self.ctx.quadraticCurveTo(r, b, r - radius, b);
self.ctx.lineTo(x + radius, b);
self.ctx.quadraticCurveTo(x, b, x, b - radius);
self.ctx.lineTo(x, y + radius);
self.ctx.quadraticCurveTo(x, y, x + radius, y);
}
function fillRect(x, y, w, h) {
x += self.canvasOffsetLeft;
y += self.canvasOffsetTop;
self.ctx.fillRect(x, y, w, h);
}
function strokeRect(x, y, w, h) {
x += self.canvasOffsetLeft;
y += self.canvasOffsetTop;
self.ctx.strokeRect(x, y, w, h);
}
function fillText(text, x, y) {
x += self.canvasOffsetLeft;
y += self.canvasOffsetTop;
self.ctx.fillText(text, x, y);
}
function fillCircle(x, y, r) {
x += self.canvasOffsetLeft;
y += self.canvasOffsetTop;
self.ctx.beginPath();
self.ctx.arc(x, y, r, 0, 2 * Math.PI);
self.ctx.fill();
}
function strokeCircle(x, y, r) {
x += self.canvasOffsetLeft;
y += self.canvasOffsetTop;
self.ctx.beginPath();
self.ctx.arc(x, y, r, 0, 2 * Math.PI);
self.ctx.stroke();
}
function clipFrozenArea(mode) {
// 0 both, 1 rows, 2 cols
// self.lastFrozenColumnPixel;
// self.lastFrozenRowPixel;
self.ctx.beginPath();
if (mode === 0) {
self.ctx.moveTo(self.lastFrozenColumnPixel, self.lastFrozenRowPixel);
self.ctx.lineTo(self.lastFrozenColumnPixel, self.height);
self.ctx.lineTo(self.width, self.height);
self.ctx.lineTo(self.width, self.lastFrozenRowPixel);
}
if (mode === 1) {
self.ctx.moveTo(0, self.lastFrozenRowPixel);
self.ctx.lineTo(0, self.height);
self.ctx.lineTo(self.width, self.height);
self.ctx.lineTo(self.width, self.lastFrozenRowPixel);
}
if (mode === 2) {
self.ctx.moveTo(self.lastFrozenColumnPixel, 0);
self.ctx.lineTo(self.width, 0);
self.ctx.lineTo(self.width, self.height);
self.ctx.lineTo(self.lastFrozenColumnPixel, self.height);
}
self.ctx.clip();
}
function fillHandle(x, y, r) {
if (self.style.selectionHandleType === 'circle') {
return fillCircle(x, y, r * 0.5);
}
fillRect(x - r * 0.5, y - r * 0.5, r, r);
}
function strokeHandle(x, y, r) {
if (self.style.selectionHandleType === 'circle') {
return strokeCircle(x, y, r * 0.5);
}
strokeRect(x - r * 0.5, y - r * 0.5, r, r);
}
function addselectionHandle(c, pos) {
var hw = self.style.selectionHandleSize,
p = {
tr: function () {
fillHandle(c.x + c.width, c.y, hw);
strokeHandle(c.x + c.width, c.y, hw);
},
br: function () {
fillHandle(c.x + c.width, c.y + c.height, hw);
strokeHandle(c.x + c.width, c.y + c.height, hw);
},
tl: function () {
fillHandle(c.x, c.y, hw);
strokeHandle(c.x, c.y, hw);
},
bl: function () {
fillHandle(c.x, c.y + c.height, hw);
strokeHandle(c.x, c.y + c.height, hw);
}
};
p[pos]();
}
function addBorderLine(c, pos) {
self.ctx.beginPath();
var p = {
t: function () {
self.ctx.moveTo(c.x + self.canvasOffsetLeft, c.y + self.canvasOffsetTop);
self.ctx.lineTo(c.x + self.canvasOffsetLeft + c.width, c.y + self.canvasOffsetTop);
},
r: function () {
self.ctx.moveTo(c.x + self.canvasOffsetLeft + c.width, c.y + self.canvasOffsetTop);
self.ctx.lineTo(c.x + self.canvasOffsetLeft + c.width, c.y + self.canvasOffsetTop + c.height);
},
b: function () {
self.ctx.moveTo(c.x + self.canvasOffsetLeft, c.y + self.canvasOffsetTop + c.height);
self.ctx.lineTo(c.x + self.canvasOffsetLeft + c.width, c.y + self.canvasOffsetTop + c.height);
},
l: function () {
self.ctx.moveTo(c.x + self.canvasOffsetLeft, c.y + self.canvasOffsetTop);
self.ctx.lineTo(c.x + self.canvasOffsetLeft, c.y + self.canvasOffsetTop + c.height);
}
};
p[pos]();
self.ctx.stroke();
}
function addEllipsis(text, width) {
var c, w = 0;
if (self.ellipsisCache[text] && self.ellipsisCache[text][width]) {
return self.ellipsisCache[text][width];
}
//TODO Add ellipsis back when there is a fast way to do it
w = self.ctx.measureText(text).width;
self.ellipsisCache[text] = self.ellipsisCache[text] || {};
c = {value: text, width: w};
self.ellipsisCache[text][width] = c;
return c;
}
function drawText(cell) {
var paddingLeft = self.style[cell.style + 'PaddingLeft'] * self.scale,
paddingTop = self.style[cell.style + 'PaddingTop'] * self.scale,
paddingRight = self.style[cell.style + 'PaddingRight'] * self.scale,
paddingBottom = self.style[cell.style + 'PaddingBottom'] * self.scale,
vPos = paddingTop + cell.height - (cell.height * 0.5),
hPos = paddingLeft + cell.treeArrowWidth + cell.orderByArrowWidth;
cell.text = addEllipsis(cell.formattedValue, cell.width - paddingRight - paddingLeft);
cell.text.height = cell.fontHeight;
if (cell.horizontalAlignment === 'right') {
hPos = cell.width - cell.text.width - paddingRight;
} else if (cell.horizontalAlignment === 'center') {
hPos = (cell.width / 2) - (cell.text.width / 2);
}
if (cell.verticalAlignment === 'top') {
vPos = paddingTop + cell.text.height;
} else if (cell.verticalAlignment === 'bottom') {
vPos = cell.height - paddingBottom - cell.text.height;
}
cell.text.x = cell.x + hPos;
cell.text.y = cell.y + vPos;
fillText(cell.text.value, cell.text.x, cell.text.y);
}
function getFrozenColumnsWidth() {
var w = 0,
s = self.getVisibleSchema(),
x = 0,
n = Math.min(self.frozenColumn, s.length),
column;
while (x < n) {
column = s[self.orders.columns[x]];
w += ((self.sizes.columns[column[self.uniqueId]] || column.width || self.style.cellWidth) * self.scale);
x += 1;
}
return w;
}
/**
* Redraws the grid. No matter what the change, this is the only method required to refresh everything.
* @memberof canvasDatagrid
* @name draw
* @method
*/
// r = literal row index
// rd = row data array
// i = user order index
// o = literal data index
// y = y drawing cursor
// x = x drawing cursor
// s = visible schema array
// cx = current x drawing cursor sub calculation var
// cy = current y drawing cursor sub calculation var
// a = static cell (like corner cell)
// p = perf counter
// l = data length
// u = current cell
// h = current height
// w = current width
self.draw = function (internal) {
if (self.dispatchEvent('beforedraw', {})) { return; }
if (!self.isChildGrid && (!self.height || !self.width)) {
return;
}
if (self.isChildGrid && internal) {
requestAnimationFrame(self.parentGrid.draw);
return;
}
if (self.intf.visible === false) {
return;
}
// initial values
var checkScrollHeight, rowHeaderCell, p, cx, cy, treeGrid, rowOpen,
rowHeight, cornerCell, y, x, c, h, w, s, r, rd, aCell,
bc = self.style.gridBorderCollapse === 'collapse',
selectionBorders = [],
moveBorders = [],
selectionHandles = [],
rowHeaders = [],
frozenColumnWidths = getFrozenColumnsWidth(),
l = self.data.length,
u = self.currentCell || {},
columnHeaderCellHeight = self.getColumnHeaderCellHeight(),
rowHeaderCellWidth = self.getRowHeaderCellWidth(),
cellHeight = self.style.cellHeight;
drawCount += 1;
p = performance.now();
self.visibleRowHeights = [];
// if data length has changed, there is no way to know
if (self.data.length > self.orders.rows.length) {
self.createRowOrders();
}
function drawScrollBars() {
var v = {
x: 0,
y: 0,
height: 0,
width: 0,
style: 'vertical-scroll-bar'
},
n = {
x: 0,
y: 0,
height: 0,
width: 0,
style: 'horizontal-scroll-bar'
},
vb = {
x: 0,
y: 0,
height: 0,
width: 0,
style: 'vertical-scroll-box'
},
nb = {
x: 0,
y: 0,
height: 0,
width: 0,
style: 'horizontal-scroll-box'
},
co = {
x: 0,
y: 0,
height: 0,
width: 0,
isCorner: true,
isScrollBoxCorner: true,
style: 'scroll-box-corner'
},
m = (self.style.scrollBarBoxMargin * 2),
d = self.style.scrollBarBoxMargin * 0.5;
self.ctx.strokeStyle = self.style.scrollBarBorderColor;
self.ctx.lineWidth = self.style.scrollBarBorderWidth;
// vertical
v.x += w - self.style.scrollBarWidth - self.style.scrollBarBorderWidth - d;
v.y += columnHeaderCellHeight;
v.width = self.style.scrollBarWidth + self.style.scrollBarBorderWidth + d;
v.height = h - columnHeaderCellHeight - self.style.scrollBarWidth - d - m;
self.ctx.fillStyle = self.style.scrollBarBackgroundColor;
fillRect(v.x, v.y, v.width, v.height + m);
strokeRect(v.x, v.y, v.width, v.height + m);
// vertical box
vb.x = v.x + self.style.scrollBarBoxMargin;
vb.y = columnHeaderCellHeight + self.style.scrollBarBoxMargin
+ ((v.height - self.scrollBox.scrollBoxHeight)
* (self.scrollBox.scrollTop / self.scrollBox.scrollHeight));
vb.width = self.style.scrollBarBoxWidth;
vb.height = self.scrollBox.scrollBoxHeight;
self.ctx.fillStyle = self.style.scrollBarBoxColor;
if (/vertical/.test(u.context)) {
self.ctx.fillStyle = self.style.scrollBarActiveColor;
}
if (vb.height < v.height) {
radiusRect(vb.x, vb.y, vb.width, vb.height, self.style.scrollBarBoxBorderRadius);
self.ctx.stroke();
self.ctx.fill();
}
// horizontal
n.x += rowHeaderC