2020-02-14 18:33:08 +01:00
|
|
|
import {spritingOn, spritingOff} from './spriting';
|
|
|
|
|
2017-03-05 17:49:12 +01:00
|
|
|
function createCanvas(w, h) {
|
|
|
|
var canvas = document.createElement('canvas');
|
|
|
|
canvas.width = w;
|
|
|
|
canvas.height = h;
|
|
|
|
return canvas;
|
|
|
|
}
|
|
|
|
|
|
|
|
function readImageData(url, callback) {
|
|
|
|
var image = new Image();
|
|
|
|
|
|
|
|
image.onload = function() {
|
|
|
|
var h = image.height;
|
|
|
|
var w = image.width;
|
|
|
|
var canvas = createCanvas(w, h);
|
|
|
|
var ctx = canvas.getContext('2d');
|
|
|
|
ctx.drawImage(image, 0, 0, w, h);
|
|
|
|
callback(ctx.getImageData(0, 0, w, h));
|
|
|
|
};
|
|
|
|
|
|
|
|
image.src = url;
|
|
|
|
}
|
|
|
|
|
2017-03-04 16:47:53 +01:00
|
|
|
/**
|
2019-01-28 19:40:07 +01:00
|
|
|
* Injects a new canvas (and div wrapper) and creates the associated Chart instance
|
2017-03-04 16:47:53 +01:00
|
|
|
* using the given config. Additional options allow tweaking elements generation.
|
|
|
|
* @param {object} config - Chart config.
|
|
|
|
* @param {object} options - Chart acquisition options.
|
|
|
|
* @param {object} options.canvas - Canvas attributes.
|
|
|
|
* @param {object} options.wrapper - Canvas wrapper attributes.
|
2020-03-06 18:17:12 +01:00
|
|
|
* @param {boolean} options.useOffscreenCanvas - use an OffscreenCanvas instead of the normal HTMLCanvasElement.
|
2020-11-20 21:59:48 +01:00
|
|
|
* @param {boolean} options.useShadowDOM - use shadowDom
|
2017-03-04 16:47:53 +01:00
|
|
|
* @param {boolean} options.persistent - If true, the chart will not be released after the spec.
|
|
|
|
*/
|
|
|
|
function acquireChart(config, options) {
|
|
|
|
var wrapper = document.createElement('div');
|
|
|
|
var canvas = document.createElement('canvas');
|
|
|
|
var chart, key;
|
|
|
|
|
|
|
|
config = config || {};
|
|
|
|
options = options || {};
|
|
|
|
options.canvas = options.canvas || {height: 512, width: 512};
|
|
|
|
options.wrapper = options.wrapper || {class: 'chartjs-wrapper'};
|
|
|
|
|
|
|
|
for (key in options.canvas) {
|
2019-10-31 23:03:00 +01:00
|
|
|
if (Object.prototype.hasOwnProperty.call(options.canvas, key)) {
|
2017-03-04 16:47:53 +01:00
|
|
|
canvas.setAttribute(key, options.canvas[key]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (key in options.wrapper) {
|
2019-10-31 23:03:00 +01:00
|
|
|
if (Object.prototype.hasOwnProperty.call(options.wrapper, key)) {
|
2017-03-04 16:47:53 +01:00
|
|
|
wrapper.setAttribute(key, options.wrapper[key]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// by default, remove chart animation and auto resize
|
|
|
|
config.options = config.options || {};
|
2017-07-22 14:13:09 +02:00
|
|
|
config.options.animation = config.options.animation === undefined ? false : config.options.animation;
|
|
|
|
config.options.responsive = config.options.responsive === undefined ? false : config.options.responsive;
|
2020-02-03 13:36:31 +01:00
|
|
|
config.options.locale = config.options.locale || 'en-US';
|
2017-03-04 16:47:53 +01:00
|
|
|
|
2020-11-20 21:59:48 +01:00
|
|
|
if (options.useShadowDOM) {
|
|
|
|
if (!wrapper.attachShadow) {
|
|
|
|
// If shadowDOM is not supported by the browsers, mark test as 'pending'.
|
|
|
|
return pending();
|
|
|
|
}
|
|
|
|
wrapper.attachShadow({mode: 'open'}).appendChild(canvas);
|
|
|
|
} else {
|
|
|
|
wrapper.appendChild(canvas);
|
|
|
|
}
|
2017-03-04 16:47:53 +01:00
|
|
|
window.document.body.appendChild(wrapper);
|
|
|
|
|
2017-10-07 17:43:09 +02:00
|
|
|
try {
|
2020-03-06 18:17:12 +01:00
|
|
|
var ctx;
|
|
|
|
if (options.useOffscreenCanvas) {
|
|
|
|
if (!canvas.transferControlToOffscreen) {
|
|
|
|
// If this browser does not support offscreen canvas, mark the test as 'pending', which will skip the
|
|
|
|
// test.
|
|
|
|
// TODO: switch to skip() once it's implemented (https://github.com/jasmine/jasmine/issues/1709), or
|
|
|
|
// remove if all browsers implement `transferControlToOffscreen`
|
2020-11-20 21:59:48 +01:00
|
|
|
return pending();
|
2020-03-06 18:17:12 +01:00
|
|
|
}
|
|
|
|
var offscreenCanvas = canvas.transferControlToOffscreen();
|
|
|
|
ctx = offscreenCanvas.getContext('2d');
|
|
|
|
} else {
|
|
|
|
ctx = canvas.getContext('2d');
|
|
|
|
}
|
2020-02-14 18:33:08 +01:00
|
|
|
if (options.spriteText) {
|
|
|
|
spritingOn(ctx);
|
|
|
|
}
|
|
|
|
chart = new Chart(ctx, config);
|
2017-10-07 17:43:09 +02:00
|
|
|
} catch (e) {
|
|
|
|
window.document.body.removeChild(wrapper);
|
|
|
|
throw e;
|
|
|
|
}
|
|
|
|
|
2017-03-04 16:47:53 +01:00
|
|
|
chart.$test = {
|
|
|
|
persistent: options.persistent,
|
|
|
|
wrapper: wrapper
|
|
|
|
};
|
|
|
|
|
|
|
|
return chart;
|
|
|
|
}
|
|
|
|
|
|
|
|
function releaseChart(chart) {
|
2020-02-14 18:33:08 +01:00
|
|
|
spritingOff(chart.ctx);
|
2017-03-04 16:47:53 +01:00
|
|
|
chart.destroy();
|
|
|
|
|
|
|
|
var wrapper = (chart.$test || {}).wrapper;
|
|
|
|
if (wrapper && wrapper.parentNode) {
|
|
|
|
wrapper.parentNode.removeChild(wrapper);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function injectCSS(css) {
|
2018-12-16 11:58:29 +01:00
|
|
|
// https://stackoverflow.com/q/3922139
|
2017-03-04 16:47:53 +01:00
|
|
|
var head = document.getElementsByTagName('head')[0];
|
|
|
|
var style = document.createElement('style');
|
|
|
|
style.setAttribute('type', 'text/css');
|
2017-07-22 09:19:06 +02:00
|
|
|
if (style.styleSheet) { // IE
|
2017-03-04 16:47:53 +01:00
|
|
|
style.styleSheet.cssText = css;
|
|
|
|
} else {
|
|
|
|
style.appendChild(document.createTextNode(css));
|
|
|
|
}
|
|
|
|
head.appendChild(style);
|
|
|
|
}
|
|
|
|
|
2017-07-26 13:33:45 +02:00
|
|
|
function waitForResize(chart, callback) {
|
|
|
|
var override = chart.resize;
|
|
|
|
chart.resize = function() {
|
|
|
|
chart.resize = override;
|
|
|
|
override.apply(this, arguments);
|
|
|
|
callback();
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2020-01-14 13:34:08 +01:00
|
|
|
function afterEvent(chart, type, callback) {
|
2020-02-10 23:57:22 +01:00
|
|
|
var override = chart._eventHandler;
|
|
|
|
chart._eventHandler = function(event) {
|
2020-01-14 13:34:08 +01:00
|
|
|
override.call(this, event);
|
|
|
|
if (event.type === type) {
|
2020-02-10 23:57:22 +01:00
|
|
|
chart._eventHandler = override;
|
2020-01-14 13:34:08 +01:00
|
|
|
// eslint-disable-next-line callback-return
|
|
|
|
callback();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2019-01-20 08:09:21 +01:00
|
|
|
function _resolveElementPoint(el) {
|
|
|
|
var point = {x: 0, y: 0};
|
|
|
|
if (el) {
|
|
|
|
if (typeof el.getCenterPoint === 'function') {
|
|
|
|
point = el.getCenterPoint();
|
|
|
|
} else if (el.x !== undefined && el.y !== undefined) {
|
|
|
|
point = el;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return point;
|
|
|
|
}
|
|
|
|
|
2017-08-24 09:34:38 +02:00
|
|
|
function triggerMouseEvent(chart, type, el) {
|
|
|
|
var node = chart.canvas;
|
|
|
|
var rect = node.getBoundingClientRect();
|
2019-01-20 08:09:21 +01:00
|
|
|
var point = _resolveElementPoint(el);
|
2017-08-24 09:34:38 +02:00
|
|
|
var event = new MouseEvent(type, {
|
2019-01-20 08:09:21 +01:00
|
|
|
clientX: rect.left + point.x,
|
|
|
|
clientY: rect.top + point.y,
|
2017-08-24 09:34:38 +02:00
|
|
|
cancelable: true,
|
|
|
|
bubbles: true,
|
|
|
|
view: window
|
|
|
|
});
|
|
|
|
|
|
|
|
node.dispatchEvent(event);
|
|
|
|
}
|
|
|
|
|
2020-02-14 18:33:08 +01:00
|
|
|
export default {
|
2017-03-04 16:47:53 +01:00
|
|
|
injectCSS: injectCSS,
|
2017-03-05 17:49:12 +01:00
|
|
|
createCanvas: createCanvas,
|
2017-03-04 16:47:53 +01:00
|
|
|
acquireChart: acquireChart,
|
2017-03-05 17:49:12 +01:00
|
|
|
releaseChart: releaseChart,
|
2018-10-20 11:38:48 +02:00
|
|
|
readImageData: readImageData,
|
2017-08-24 09:34:38 +02:00
|
|
|
triggerMouseEvent: triggerMouseEvent,
|
2020-01-14 13:34:08 +01:00
|
|
|
waitForResize: waitForResize,
|
|
|
|
afterEvent: afterEvent
|
2017-03-04 16:47:53 +01:00
|
|
|
};
|