Skip to content

Commit bb46a30

Browse files
committed
Release 1.0.0
1 parent 62d697b commit bb46a30

File tree

3 files changed

+213
-0
lines changed

3 files changed

+213
-0
lines changed

bower.json

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"name": "chartjs-plugin-deferred",
3+
"description": "Chart.js plugin to defer initial chart updates",
4+
"homepage": "https://chartjs-plugin-deferred.netlify.com",
5+
"license": "MIT",
6+
"version": "1.0.0",
7+
"main": "distchartjs-plugin-deferred.js"
8+
}

dist/chartjs-plugin-deferred.js

Lines changed: 194 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,194 @@
1+
/*
2+
* @license
3+
* chartjs-plugin-deferred
4+
* http://chartjs.org/
5+
* Version: 1.0.0
6+
*
7+
* Copyright 2018 Simon Brunel
8+
* Released under the MIT license
9+
* https://github.com/chartjs/chartjs-plugin-deferred/blob/master/LICENSE.md
10+
*/
11+
(function (global, factory) {
12+
typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('chart.js')) :
13+
typeof define === 'function' && define.amd ? define(['chart.js'], factory) :
14+
(factory(global.Chart));
15+
}(this, (function (Chart) { 'use strict';
16+
17+
Chart = Chart && Chart.hasOwnProperty('default') ? Chart['default'] : Chart;
18+
19+
'use strict';
20+
21+
var helpers = Chart.helpers;
22+
var STUB_KEY = '$chartjs_deferred';
23+
var MODEL_KEY = '$deferred';
24+
25+
/**
26+
* Plugin based on discussion from Chart.js issue #2745.
27+
* @see https://github.com/chartjs/Chart.js/issues/2745
28+
*/
29+
Chart.defaults.global.plugins.deferred = {
30+
xOffset: 0,
31+
yOffset: 0,
32+
delay: 0
33+
};
34+
35+
function defer(fn, delay) {
36+
if (delay) {
37+
window.setTimeout(fn, delay);
38+
} else {
39+
helpers.requestAnimFrame.call(window, fn);
40+
}
41+
}
42+
43+
function computeOffset(value, base) {
44+
var number = parseInt(value, 10);
45+
if (isNaN(number)) {
46+
return 0;
47+
} else if (typeof value === 'string' && value.indexOf('%') !== -1) {
48+
return number / 100 * base;
49+
}
50+
return number;
51+
}
52+
53+
function chartInViewport(chart) {
54+
var options = chart[MODEL_KEY].options;
55+
var canvas = chart.chart.canvas;
56+
57+
// http://stackoverflow.com/a/21696585
58+
if (!canvas || canvas.offsetParent === null) {
59+
return false;
60+
}
61+
62+
var rect = canvas.getBoundingClientRect();
63+
var dy = computeOffset(options.yOffset || 0, rect.height);
64+
var dx = computeOffset(options.xOffset || 0, rect.width);
65+
66+
return rect.right - dx >= 0
67+
&& rect.bottom - dy >= 0
68+
&& rect.left + dx <= window.innerWidth
69+
&& rect.top + dy <= window.innerHeight;
70+
}
71+
72+
function onScroll(event) {
73+
var node = event.target;
74+
var stub = node[STUB_KEY];
75+
if (stub.ticking) {
76+
return;
77+
}
78+
79+
stub.ticking = true;
80+
defer(function() {
81+
var charts = stub.charts.slice();
82+
var ilen = charts.length;
83+
var chart, i;
84+
85+
for (i = 0; i < ilen; ++i) {
86+
chart = charts[i];
87+
if (chartInViewport(chart)) {
88+
unwatch(chart); // eslint-disable-line
89+
chart[MODEL_KEY].appeared = true;
90+
chart.update();
91+
}
92+
}
93+
94+
stub.ticking = false;
95+
});
96+
}
97+
98+
function isScrollable(node) {
99+
var type = node.nodeType;
100+
if (type === Node.ELEMENT_NODE) {
101+
var overflowX = helpers.getStyle(node, 'overflow-x');
102+
var overflowY = helpers.getStyle(node, 'overflow-y');
103+
return overflowX === 'auto' || overflowX === 'scroll'
104+
|| overflowY === 'auto' || overflowY === 'scroll';
105+
}
106+
107+
return node.nodeType === Node.DOCUMENT_NODE;
108+
}
109+
110+
function watch(chart) {
111+
var canvas = chart.chart.canvas;
112+
var parent = canvas.parentElement;
113+
var stub, charts;
114+
115+
while (parent) {
116+
if (isScrollable(parent)) {
117+
stub = parent[STUB_KEY] || (parent[STUB_KEY] = {});
118+
charts = stub.charts || (stub.charts = []);
119+
if (charts.length === 0) {
120+
parent.addEventListener('scroll', onScroll, {passive: true});
121+
}
122+
123+
charts.push(chart);
124+
chart[MODEL_KEY].elements.push(parent);
125+
}
126+
127+
parent = parent.parentElement || parent.ownerDocument;
128+
}
129+
}
130+
131+
function unwatch(chart) {
132+
chart[MODEL_KEY].elements.forEach(function(element) {
133+
var charts = element[STUB_KEY].charts;
134+
charts.splice(charts.indexOf(chart), 1);
135+
if (!charts.length) {
136+
helpers.removeEvent(element, 'scroll', onScroll);
137+
delete element[STUB_KEY];
138+
}
139+
});
140+
141+
chart[MODEL_KEY].elements = [];
142+
}
143+
144+
Chart.plugins.register({
145+
id: 'deferred',
146+
147+
beforeInit: function(chart, options) {
148+
chart[MODEL_KEY] = {
149+
options: options,
150+
appeared: false,
151+
delayed: false,
152+
loaded: false,
153+
elements: []
154+
};
155+
156+
watch(chart);
157+
},
158+
159+
beforeDatasetsUpdate: function(chart, options) {
160+
var model = chart[MODEL_KEY];
161+
if (!model.loaded) {
162+
if (!model.appeared && !chartInViewport(chart)) {
163+
// cancel the datasets update
164+
return false;
165+
}
166+
167+
model.appeared = true;
168+
model.loaded = true;
169+
unwatch(chart);
170+
171+
if (options.delay > 0) {
172+
model.delayed = true;
173+
defer(function() {
174+
model.delayed = false;
175+
chart.update();
176+
}, options.delay);
177+
178+
return false;
179+
}
180+
}
181+
182+
if (model.delayed) {
183+
// in case of delayed update, ensure to block external requests, such
184+
// as interacting with the legend label, or direct calls to update()
185+
return false;
186+
}
187+
},
188+
189+
destroy: function(chart) {
190+
unwatch(chart);
191+
}
192+
});
193+
194+
})));

dist/chartjs-plugin-deferred.min.js

Lines changed: 11 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)