diff --git a/src/core/core.controller.js b/src/core/core.controller.js
index 1dbf90f01..5ae591d41 100644
--- a/src/core/core.controller.js
+++ b/src/core/core.controller.js
@@ -731,9 +731,7 @@ module.exports = function(Chart) {
listeners[type] = listener;
});
- // Responsiveness is currently based on the use of an iframe, however this method causes
- // performance issues and could be troublesome when used with ad blockers. So make sure
- // that the user is still able to create a chart without iframe when responsive is false.
+ // Elements used to detect size change should not be injected for non responsive charts.
// See https://github.com/chartjs/Chart.js/issues/2210
if (me.options.responsive) {
listener = function() {
diff --git a/src/platforms/platform.dom.js b/src/platforms/platform.dom.js
index 2659ac6a4..8fe9f2707 100644
--- a/src/platforms/platform.dom.js
+++ b/src/platforms/platform.dom.js
@@ -165,43 +165,62 @@ function throttled(fn, thisArg) {
};
}
+// Implementation based on https://github.com/marcj/css-element-queries
function createResizer(handler) {
- var iframe = document.createElement('iframe');
- iframe.className = 'chartjs-hidden-iframe';
- iframe.style.cssText =
- 'display:block;' +
- 'overflow:hidden;' +
- 'border:0;' +
- 'margin:0;' +
- 'top:0;' +
- 'left:0;' +
- 'bottom:0;' +
- 'right:0;' +
- 'height:100%;' +
- 'width:100%;' +
+ var resizer = document.createElement('div');
+ var cls = CSS_PREFIX + 'size-monitor';
+ var maxSize = 1000000;
+ var style =
'position:absolute;' +
+ 'left:0;' +
+ 'top:0;' +
+ 'right:0;' +
+ 'bottom:0;' +
+ 'overflow:hidden;' +
'pointer-events:none;' +
+ 'visibility:hidden;' +
'z-index:-1;';
- // Prevent the iframe to gain focus on tab.
- // https://github.com/chartjs/Chart.js/issues/3090
- iframe.tabIndex = -1;
+ resizer.style.cssText = style;
+ resizer.className = cls;
+ resizer.innerHTML =
+ '
' +
+ '';
- // Prevent iframe from gaining focus on ItemMode keyboard navigation
- // Accessibility bug fix
- iframe.setAttribute('aria-hidden', 'true');
+ var expand = resizer.childNodes[0];
+ var shrink = resizer.childNodes[1];
- // If the iframe is re-attached to the DOM, the resize listener is removed because the
- // content is reloaded, so make sure to install the handler after the iframe is loaded.
- // https://github.com/chartjs/Chart.js/issues/3521
- addEventListener(iframe, 'load', function() {
- addEventListener(iframe.contentWindow || iframe, 'resize', handler);
- // The iframe size might have changed while loading, which can also
- // happen if the size has been changed while detached from the DOM.
+ resizer._reset = function() {
+ expand.scrollLeft = maxSize;
+ expand.scrollTop = maxSize;
+ shrink.scrollLeft = maxSize;
+ shrink.scrollTop = maxSize;
+ };
+ var onScroll = function() {
+ resizer._reset();
handler();
- });
+ };
- return iframe;
+ addEventListener(expand, 'scroll', onScroll.bind(expand, 'expand'));
+ addEventListener(shrink, 'scroll', onScroll.bind(shrink, 'shrink'));
+
+ return resizer;
}
// https://davidwalsh.name/detect-node-insertion
@@ -253,6 +272,9 @@ function addResizeListener(node, listener, chart) {
if (container && container !== resizer.parentNode) {
container.insertBefore(resizer, container.firstChild);
}
+
+ // The container size might have changed, let's reset the resizer state.
+ resizer._reset();
}
});
}
diff --git a/test/specs/core.controller.tests.js b/test/specs/core.controller.tests.js
index 24f062b78..76740315a 100644
--- a/test/specs/core.controller.tests.js
+++ b/test/specs/core.controller.tests.js
@@ -420,7 +420,8 @@ describe('Chart', function() {
waitForResize(chart, function() {
var resizer = wrapper.firstChild;
- expect(resizer.tagName).toBe('IFRAME');
+ expect(resizer.className).toBe('chartjs-size-monitor');
+ expect(resizer.tagName).toBe('DIV');
expect(chart).toBeChartOfSize({
dw: 455, dh: 355,
rw: 455, rh: 355,
@@ -687,7 +688,8 @@ describe('Chart', function() {
var wrapper = chart.canvas.parentNode;
var resizer = wrapper.firstChild;
expect(wrapper.childNodes.length).toBe(2);
- expect(resizer.tagName).toBe('IFRAME');
+ expect(resizer.className).toBe('chartjs-size-monitor');
+ expect(resizer.tagName).toBe('DIV');
chart.destroy();