this.attached = false;
this._animationsDisabled = undefined;
this.$context = undefined;
- this._doResize = debounce(() => this.update('resize'), options.resizeDelay || 0);
+ this._doResize = debounce(mode => this.update(mode), options.resizeDelay || 0);
// Add the chart instance to the global namespace
instances[me.id] = me;
const aspectRatio = options.maintainAspectRatio && me.aspectRatio;
const newSize = me.platform.getMaximumSize(canvas, width, height, aspectRatio);
const newRatio = options.devicePixelRatio || me.platform.getDevicePixelRatio();
+ const mode = me.width ? 'resize' : 'attach';
me.width = newSize.width;
me.height = newSize.height;
callCallback(options.onResize, [me, newSize], me);
if (me.attached) {
- if (me._doResize()) {
+ if (me._doResize(mode)) {
// The resize update is delayed, only draw without updating.
me.render();
}
}
}
- destroy() {
+ _stop() {
const me = this;
- const {canvas, ctx} = me;
let i, ilen;
-
me.stop();
animator.remove(me);
- // dataset controllers need to cleanup associated data
for (i = 0, ilen = me.data.datasets.length; i < ilen; ++i) {
me._destroyDatasetMeta(i);
}
+ }
+
+ destroy() {
+ const me = this;
+ const {canvas, ctx} = me;
+ me._stop();
me.config.clearCache();
if (canvas) {
me.attached = false;
_remove('resize', listener);
+
+ // Stop animating and remove metasets, so when re-attached, the animations start from begining.
+ me._stop();
+ me._resize(0, 0);
+
_add('attach', attached);
};
/**
* Debounces calling `fn` for `delay` ms
- * @param {function} fn - Function to call. No arguments are passed.
+ * @param {function} fn - Function to call.
* @param {number} delay - Delay in ms. 0 = immediate invocation.
* @returns {function}
*/
export function debounce(fn, delay) {
let timeout;
- return function() {
+ return function(...args) {
if (delay) {
clearTimeout(timeout);
- timeout = setTimeout(fn, delay);
+ timeout = setTimeout(fn, delay, args);
} else {
- fn();
+ fn.apply(this, args);
}
return delay;
};
}
-
/**
* Converts 'start' to 'left', 'end' to 'right' and others to 'center'
* @param {string} align start, end, center
function createAttachObserver(chart, type, listener) {
const canvas = chart.canvas;
- const container = canvas && _getParentNode(canvas);
- const element = container || canvas;
const observer = new MutationObserver(entries => {
- const parent = _getParentNode(element);
- entries.forEach(entry => {
- for (let i = 0; i < entry.addedNodes.length; i++) {
- const added = entry.addedNodes[i];
- if (added === element || added === parent) {
- listener(entry.target);
+ for (const entry of entries) {
+ for (const node of entry.addedNodes) {
+ if (node === canvas || node.contains(canvas)) {
+ return listener();
}
}
- });
+ }
});
observer.observe(document, {childList: true, subtree: true});
return observer;
function createDetachObserver(chart, type, listener) {
const canvas = chart.canvas;
- const container = canvas && _getParentNode(canvas);
- if (!container) {
- return;
- }
const observer = new MutationObserver(entries => {
- entries.forEach(entry => {
- for (let i = 0; i < entry.removedNodes.length; i++) {
- if (entry.removedNodes[i] === canvas) {
- listener();
- break;
+ for (const entry of entries) {
+ for (const node of entry.removedNodes) {
+ if (node === canvas || node.contains(canvas)) {
+ return listener();
}
}
- });
+ }
});
- observer.observe(container, {childList: true});
+ observer.observe(document, {childList: true, subtree: true});
return observer;
}
});
parent.removeChild(wrapper);
- parent.appendChild(wrapper);
- wrapper.style.height = '355px';
+ setTimeout(() => {
+ parent.appendChild(wrapper);
+ wrapper.style.height = '355px';
+ }, 0);
});
// https://github.com/chartjs/Chart.js/issues/4737
canvas.parentNode.style.width = '455px';
});
});
+
+ it('should resize the canvas if attached to the DOM after construction with mutiple parents', function(done) {
+ var canvas = document.createElement('canvas');
+ var wrapper = document.createElement('div');
+ var wrapper2 = document.createElement('div');
+ var wrapper3 = document.createElement('div');
+ var body = window.document.body;
+
+ var chart = new Chart(canvas, {
+ type: 'line',
+ options: {
+ responsive: true,
+ maintainAspectRatio: false
+ }
+ });
+
+ expect(chart).toBeChartOfSize({
+ dw: 0, dh: 0,
+ rw: 0, rh: 0,
+ });
+ expect(chart.chartArea).toBeUndefined();
+
+ waitForResize(chart, function() {
+ expect(chart).toBeChartOfSize({
+ dw: 455, dh: 355,
+ rw: 455, rh: 355,
+ });
+
+ expect(chart.chartArea).not.toBeUndefined();
+
+ body.removeChild(wrapper3);
+ chart.destroy();
+ done();
+ });
+
+ wrapper3.appendChild(wrapper2);
+ wrapper2.appendChild(wrapper);
+ wrapper.style.cssText = 'width: 455px; height: 355px';
+ wrapper.appendChild(canvas);
+ body.appendChild(wrapper3);
+ });
});
describe('config.options.responsive: true (maintainAspectRatio: true)', function() {