rewrote the onscroll handler; supported browser passive events; dashboard are now rendered when the page has no focus, but it is scrolled
Costa Tsaousis (ktsaou) committed
Nov 18, 2017 at 21:59 UTC
3e226bd1b364d3fedbb2e1846cd85d3252462027
2 files changed
+169
-87
web/dashboard.js
+168
-86
@@ -310,6 +310,8 @@ var NETDATA = window.NETDATA || {};
310
highlight_after: null, // highlight after this time
311
highlight_before: null, // highlight before this time
312
313
+ passive_events: null, // true if the browser supports passive events
314
+
315
// the current profile
316
// we may have many...
317
current: {
@@ -632,6 +634,8 @@ var NETDATA = window.NETDATA || {};
634
if(NETDATA.onscroll_updater_enabled === false)
635
return;
636
637
+ //console.log('onscroll_updater() begin');
638
+
639
NETDATA.globalSelectionSync.stop();
640
641
NETDATA.onscroll_updater_count++;
@@ -646,11 +650,18 @@ var NETDATA = window.NETDATA || {};
650
if(NETDATA.options.abort_ajax_on_scroll === true)
651
NETDATA.abort_all_refreshes();
652
649
- // find which charts are visible
653
var targets = NETDATA.options.targets;
654
var len = targets.length;
652
- while (len--)
653
- targets[len].isVisible();
655
+
656
+ function onscroll_updater_chart_is_visible() {
657
+ if(len--) {
658
+ targets[len].isVisible();
659
+ NETDATA.onscroll_updater_timeout_id = setTimeout(onscroll_updater_chart_is_visible, 0);
660
+ }
661
+ else
662
+ NETDATA.onscroll_updater_timeout_id = 0;
663
+ }
664
+ onscroll_updater_chart_is_visible();
665
666
var end = Date.now();
667
// console.log('scroll No ' + NETDATA.onscroll_updater_count + ' calculation took ' + (end - start).toString() + ' ms');
@@ -674,13 +685,15 @@ var NETDATA = window.NETDATA || {};
685
}
686
687
NETDATA.onscroll_updater_timeout_id = 0;
688
+ //console.log('onscroll_updater() done in ' + (end - start).toString() + ' ms');
689
};
690
691
NETDATA.scrollUp = false;
692
NETDATA.scrollY = window.scrollY;
693
NETDATA.onscroll = function() {
682
- // console.log('onscroll');
694
+ //console.log('onscroll() begin');
695
696
+ NETDATA.chartRefresherReschedule();
697
NETDATA.scrollUp = (window.scrollY > NETDATA.scrollY);
698
NETDATA.scrollY = window.scrollY;
699
@@ -700,10 +713,34 @@ var NETDATA = window.NETDATA || {};
713
// sync
714
NETDATA.onscroll_updater();
715
}
716
+
717
+ //console.log('onscroll() end');
718
};
719
705
- window.onresize = NETDATA.onresize;
706
- window.onscroll = NETDATA.onscroll;
720
+ NETDATA.supportsPassiveEvents = function() {
721
+ if(NETDATA.options.passive_events === null) {
722
+ var supportsPassive = false;
723
+ try {
724
+ var opts = Object.defineProperty({}, 'passive', {
725
+ get: function () {
726
+ supportsPassive = true;
727
+ }
728
+ });
729
+ window.addEventListener("test", null, opts);
730
+ } catch (e) {
731
+ }
732
+
733
+ NETDATA.options.passive_events = supportsPassive;
734
+ }
735
+
736
+ // console.log('passive ' + NETDATA.options.passive_events);
737
+ return NETDATA.options.passive_events;
738
+ };
739
+
740
+ window.addEventListener('resize', NETDATA.onresize, NETDATA.supportsPassiveEvents() ? { passive: true } : false);
741
+ window.addEventListener('scroll', NETDATA.onscroll, NETDATA.supportsPassiveEvents() ? { passive: true } : false);
742
+ // window.onresize = NETDATA.onresize;
743
+ // window.onscroll = NETDATA.onscroll;
744
745
// ----------------------------------------------------------------------------------------------------------------
746
// Error Handling
@@ -2563,13 +2600,14 @@ var NETDATA = window.NETDATA || {};
2600
}
2601
};
2602
2566
- var canBeRendered = function() {
2603
+ var canBeRendered = function(uncached_visibility) {
2604
return (
2605
(
2606
NETDATA.options.page_is_visible === true ||
2570
- NETDATA.options.current.stop_updates_when_focus_is_lost === false
2607
+ NETDATA.options.current.stop_updates_when_focus_is_lost === false ||
2608
+ that.updates_since_last_unhide === 0
2609
)
2572
- && isHidden() === false && that.isVisible(true) === true
2610
+ && isHidden() === false && that.isVisible(uncached_visibility) === true
2611
);
2612
};
2613
@@ -2577,12 +2615,16 @@ var NETDATA = window.NETDATA || {};
2615
var callChartLibraryUpdateSafely = function(data) {
2616
var status;
2617
2580
- if(canBeRendered() === false)
2618
+ if(canBeRendered(true) === false)
2619
return false;
2620
2621
if(NETDATA.options.fake_chart_rendering === true)
2622
return true;
2623
2624
+ that.updates_counter++;
2625
+ that.updates_since_last_unhide++;
2626
+ that.updates_since_last_creation++;
2627
+
2628
if(NETDATA.options.debug.chart_errors === true)
2629
status = that.library.update(that, data);
2630
else {
@@ -2606,12 +2648,16 @@ var NETDATA = window.NETDATA || {};
2648
var callChartLibraryCreateSafely = function(data) {
2649
var status;
2650
2609
- if(canBeRendered() === false)
2651
+ if(canBeRendered(true) === false)
2652
return false;
2653
2654
if(NETDATA.options.fake_chart_rendering === true)
2655
return true;
2656
2657
+ that.updates_counter++;
2658
+ that.updates_since_last_unhide++;
2659
+ that.updates_since_last_creation++;
2660
+
2661
if(NETDATA.options.debug.chart_errors === true)
2662
status = that.library.create(that, data);
2663
else {
@@ -4096,9 +4142,6 @@ var NETDATA = window.NETDATA || {};
4142
resizeChart();
4143
4144
this.data = data;
4099
- this.updates_counter++;
4100
- this.updates_since_last_unhide++;
4101
- this.updates_since_last_creation++;
4145
4146
var started = Date.now();
4147
var view_update_every = data.view_update_every * 1000;
@@ -4290,6 +4333,7 @@ var NETDATA = window.NETDATA || {};
4333
else {
4334
ok = false;
4335
error('data not found in snapshot for key: ' + key);
4336
+ that.tm.last_autorefreshed = Date.now();
4337
}
4338
4339
NETDATA.statistics.refreshes_active--;
@@ -4394,18 +4438,16 @@ var NETDATA = window.NETDATA || {};
4438
};
4439
4440
this.canBeAutoRefreshed = function() {
4397
- var now = Date.now();
4398
-
4399
- if(this.running === true) {
4441
+ if(this.enabled === false) {
4442
if(this.debug === true)
4401
- this.log('I am already running');
4443
+ this.log('canBeAutoRefreshed() -> not enabled');
4444
4445
return false;
4446
}
4447
4406
- if(this.enabled === false) {
4448
+ if(this.running === true) {
4449
if(this.debug === true)
4408
- this.log('I am not enabled');
4450
+ this.log('canBeAutoRefreshed() -> already running');
4451
4452
return false;
4453
}
@@ -4413,88 +4455,101 @@ var NETDATA = window.NETDATA || {};
4455
if(this.library === null || this.library.enabled === false) {
4456
error('charting library "' + this.library_name + '" is not available');
4457
if(this.debug === true)
4416
- this.log('My chart library ' + this.library_name + ' is not available');
4458
+ this.log('canBeAutoRefreshed() -> chart library ' + this.library_name + ' is not available');
4459
4460
return false;
4461
}
4462
4463
if(this.isVisible() === false) {
4464
if(NETDATA.options.debug.visibility === true || this.debug === true)
4423
- this.log('I am not visible');
4465
+ this.log('canBeAutoRefreshed() -> not visible');
4466
4467
return false;
4468
}
4469
4470
+ var now = Date.now();
4471
+
4472
if(this.current.force_update_at !== 0 && this.current.force_update_at < now) {
4473
if(this.debug === true)
4430
- this.log('timed force update detected - allowing this update');
4474
+ this.log('canBeAutoRefreshed() -> timed force update - allowing this update');
4475
4476
this.current.force_update_at = 0;
4477
return true;
4478
}
4479
4436
- if(this.isAutoRefreshable() === true) {
4437
- // allow the first update, even if the page is not visible
4438
- if(this.updates_counter && this.updates_since_last_unhide && NETDATA.options.page_is_visible === false) {
4439
- // if(NETDATA.options.debug.focus === true || this.debug === true)
4440
- // this.log('canBeAutoRefreshed(): page does not have focus');
4480
+ if(this.isAutoRefreshable() === false) {
4481
+ if(this.debug === true)
4482
+ this.log('canBeAutoRefreshed() -> not auto-refreshable');
4483
4442
- return false;
4443
- }
4484
+ return false;
4485
+ }
4486
+
4487
+ // allow the first update, even if the page is not visible
4488
+ if(NETDATA.options.page_is_visible === false && this.updates_counter && this.updates_since_last_unhide) {
4489
+ if(NETDATA.options.debug.focus === true || this.debug === true)
4490
+ this.log('canBeAutoRefreshed() -> not the first update, and page does not have focus');
4491
+
4492
+ return false;
4493
+ }
4494
+
4495
+ if(this.needsRecreation() === true) {
4496
+ if(this.debug === true)
4497
+ this.log('canBeAutoRefreshed() -> needs re-creation.');
4498
+
4499
+ return true;
4500
+ }
4501
+
4502
+ if(NETDATA.options.auto_refresher_stop_until >= now) {
4503
+ if(this.debug === true)
4504
+ this.log('canBeAutoRefreshed() -> stopped until is in future.');
4505
+
4506
+ return false;
4507
+ }
4508
4445
- if(this.needsRecreation() === true) {
4509
+ // options valid only for autoRefresh()
4510
+ if(NETDATA.globalPanAndZoom.isActive()) {
4511
+ if(NETDATA.globalPanAndZoom.shouldBeAutoRefreshed(this)) {
4512
if(this.debug === true)
4447
- this.log('canBeAutoRefreshed(): needs re-creation.');
4513
+ this.log('canBeAutoRefreshed(): global panning: I need an update.');
4514
4515
return true;
4516
}
4517
+ else {
4518
+ if(this.debug === true)
4519
+ this.log('canBeAutoRefreshed(): global panning: I am already up to date.');
4520
4452
- // options valid only for autoRefresh()
4453
- if(NETDATA.options.auto_refresher_stop_until < now) {
4454
- if(NETDATA.globalPanAndZoom.isActive()) {
4455
- if(NETDATA.globalPanAndZoom.shouldBeAutoRefreshed(this)) {
4456
- if(this.debug === true)
4457
- this.log('canBeAutoRefreshed(): global panning: I need an update.');
4458
-
4459
- return true;
4460
- }
4461
- else {
4462
- if(this.debug === true)
4463
- this.log('canBeAutoRefreshed(): global panning: I am already up to date.');
4464
-
4465
- return false;
4466
- }
4467
- }
4521
+ return false;
4522
+ }
4523
+ }
4524
4469
- if(this.selected === true) {
4470
- if(this.debug === true)
4471
- this.log('canBeAutoRefreshed(): I have a selection in place.');
4525
+ if(this.selected === true) {
4526
+ if(this.debug === true)
4527
+ this.log('canBeAutoRefreshed(): I have a selection in place.');
4528
4473
- return false;
4474
- }
4529
+ return false;
4530
+ }
4531
4476
- if(this.paused === true) {
4477
- if(this.debug === true)
4478
- this.log('canBeAutoRefreshed(): I am paused.');
4532
+ if(this.paused === true) {
4533
+ if(this.debug === true)
4534
+ this.log('canBeAutoRefreshed(): I am paused.');
4535
4480
- return false;
4481
- }
4536
+ return false;
4537
+ }
4538
4483
- if(now - this.tm.last_autorefreshed >= this.data_update_every) {
4484
- if(this.debug === true)
4485
- this.log('canBeAutoRefreshed(): It is time to update me.');
4539
+ if(now - this.tm.last_autorefreshed >= this.data_update_every) {
4540
+ if(this.debug === true)
4541
+ this.log('canBeAutoRefreshed(): It is time to update me.');
4542
4487
- return true;
4488
- }
4489
- }
4543
+ return true;
4544
}
4545
4546
return false;
4547
};
4548
4549
this.autoRefresh = function(callback) {
4496
- if(this.canBeAutoRefreshed() === true && this.running === false) {
4497
- var state = this;
4550
+ var state = that;
4551
+
4552
+ if(state.canBeAutoRefreshed() === true && state.running === false) {
4553
4554
state.running = true;
4555
state.updateChart(function() {
@@ -4806,14 +4861,14 @@ var NETDATA = window.NETDATA || {};
4861
4862
// this is purely sequential charts refresher
4863
// it is meant to be autonomous
4809
- NETDATA.chartRefresherNoParallel = function(index) {
4864
+ NETDATA.chartRefresherNoParallel = function(index, callback) {
4865
if(NETDATA.options.debug.main_loop === true)
4866
console.log('NETDATA.chartRefresherNoParallel(' + index + ')');
4867
4868
if(NETDATA.options.updated_dom === true) {
4869
// the dom has been updated
4870
// get the dom parts again
4816
- NETDATA.parseDom(NETDATA.chartRefresher);
4871
+ NETDATA.parseDom(callback);
4872
return;
4873
}
4874
if(index >= NETDATA.options.targets.length) {
@@ -4821,10 +4876,7 @@ var NETDATA = window.NETDATA || {};
4876
console.log('waiting to restart main loop...');
4877
4878
NETDATA.options.auto_refresher_fast_weight = 0;
4824
-
4825
- setTimeout(function() {
4826
- NETDATA.chartRefresher();
4827
- }, NETDATA.options.current.idle_between_loops);
4879
+ callback();
4880
}
4881
else {
4882
var state = NETDATA.options.targets[index];
@@ -4835,7 +4887,7 @@ var NETDATA = window.NETDATA || {};
4887
4888
setTimeout(function() {
4889
state.autoRefresh(function () {
4838
- NETDATA.chartRefresherNoParallel(++index);
4890
+ NETDATA.chartRefresherNoParallel(++index, callback);
4891
});
4892
}, 0);
4893
}
@@ -4845,7 +4897,7 @@ var NETDATA = window.NETDATA || {};
4897
4898
setTimeout(function() {
4899
state.autoRefresh(function() {
4848
- NETDATA.chartRefresherNoParallel(++index);
4900
+ NETDATA.chartRefresherNoParallel(++index, callback);
4901
});
4902
}, NETDATA.options.current.idle_between_charts);
4903
}
@@ -4857,20 +4909,32 @@ var NETDATA = window.NETDATA || {};
4909
};
4910
4911
// the default refresher
4860
- NETDATA.chartRefresher = function() {
4861
- // console.log('auto-refresher...');
4912
+ NETDATA.chartRefresherLastRun = 0;
4913
+ NETDATA.chartRefresherTimeoutId = 0;
4914
+
4915
+ NETDATA.chartRefresherReschedule = function() {
4916
+ clearTimeout(NETDATA.chartRefresherTimeoutId);
4917
+ NETDATA.chartRefresherTimeoutId = setTimeout(NETDATA.chartRefresher, NETDATA.chartRefresherWaitTime());
4918
+ //console.log('chartRefresherReschedule()');
4919
+ };
4920
4921
+ NETDATA.chartRefresher = function() {
4922
var now = Date.now();
4923
+ //console.log('chartRefresher() begin ' + (now - NETDATA.chartRefresherLastRun).toString() + ' ms since last run');
4924
+ NETDATA.chartRefresherLastRun = now;
4925
+
4926
if( now < NETDATA.options.on_scroll_refresher_stop_until ) {
4865
- setTimeout(NETDATA.chartRefresher,
4927
+ NETDATA.chartRefresherTimeoutId = setTimeout(NETDATA.chartRefresher,
4928
NETDATA.chartRefresherWaitTime());
4929
+ //console.log('chartRefresher() end1 will run in ' + NETDATA.chartRefresherWaitTime().toString() + ' ms');
4930
return;
4931
}
4932
4933
if(NETDATA.options.pause === true) {
4934
// console.log('auto-refresher is paused');
4872
- setTimeout(NETDATA.chartRefresher,
4935
+ NETDATA.chartRefresherTimeoutId = setTimeout(NETDATA.chartRefresher,
4936
NETDATA.chartRefresherWaitTime());
4937
+ //console.log('chartRefresher() end2 will run in ' + NETDATA.chartRefresherWaitTime().toString() + ' ms');
4938
return;
4939
}
4940
@@ -4879,12 +4943,18 @@ var NETDATA = window.NETDATA || {};
4943
NETDATA.options.pause = true;
4944
NETDATA.options.pauseCallback();
4945
NETDATA.chartRefresher();
4946
+ //console.log('chartRefresher() end3 (nested)');
4947
return;
4948
}
4949
4950
if(NETDATA.options.current.parallel_refresher === false) {
4951
// console.log('auto-refresher is calling chartRefresherNoParallel(0)');
4887
- NETDATA.chartRefresherNoParallel(0);
4952
+ NETDATA.chartRefresherNoParallel(0, function() {
4953
+ NETDATA.chartRefresherTimeoutId = setTimeout(function() {
4954
+ NETDATA.chartRefresher();
4955
+ }, NETDATA.options.current.idle_between_loops);
4956
+ });
4957
+ //console.log('chartRefresher() end4 (no parallel, nested)');
4958
return;
4959
}
4960
@@ -4893,6 +4963,7 @@ var NETDATA = window.NETDATA || {};
4963
// get the dom parts again
4964
// console.log('auto-refresher is calling parseDom()');
4965
NETDATA.parseDom(NETDATA.chartRefresher);
4966
+ //console.log('chartRefresher() end5 (parseDom)');
4967
return;
4968
}
4969
@@ -4908,6 +4979,7 @@ var NETDATA = window.NETDATA || {};
4979
if(state.library.initialized === false) {
4980
if(state.library.enabled === true) {
4981
state.library.initialize(NETDATA.chartRefresher);
4982
+ //console.log('chartRefresher() end6 (library init)');
4983
return;
4984
}
4985
else {
@@ -4916,28 +4988,32 @@ var NETDATA = window.NETDATA || {};
4988
}
4989
4990
if(NETDATA.scrollUp === true)
4919
- parallel.push(state);
4920
- else
4991
parallel.unshift(state);
4992
+ else
4993
+ parallel.push(state);
4994
}
4995
4924
- if(parallel.length > 0) {
4996
+ len = parallel.length;
4997
+ while(len--) {
4998
+ var state = parallel[len];
4999
// console.log('auto-refresher executing in parallel for ' + parallel.length.toString() + ' charts');
5000
// this will execute the jobs in parallel
4927
- $(parallel).each(function() {
4928
- this.autoRefresh();
4929
- })
5001
+ setTimeout(state.autoRefresh, 0);
5002
}
5003
//else {
5004
// console.log('auto-refresher nothing to do');
5005
//}
5006
5007
// run the next refresh iteration
4936
- setTimeout(NETDATA.chartRefresher,
5008
+ NETDATA.chartRefresherTimeoutId = setTimeout(NETDATA.chartRefresher,
5009
NETDATA.chartRefresherWaitTime());
5010
+
5011
+ //console.log('chartRefresher() completed in ' + (Date.now() - now).toString() + ' ms');
5012
};
5013
5014
NETDATA.parseDom = function(callback) {
5015
+ //console.log('parseDom()');
5016
+
5017
NETDATA.options.last_page_scroll = Date.now();
5018
NETDATA.options.updated_dom = false;
5019
@@ -4959,9 +5035,15 @@ var NETDATA = window.NETDATA || {};
5035
};
5036
5037
// this is the main function - where everything starts
5038
+ NETDATA.started = false;
5039
NETDATA.start = function() {
5040
// this should be called only once
5041
5042
+ if(NETDATA.started === true)
5043
+ console.log('netdata is already started');
5044
+
5045
+ NETDATA.started = true;
5046
+
5047
NETDATA.options.page_is_visible = true;
5048
5049
$(window).blur(function() {
web/index.html
+1
-1
@@ -5288,6 +5288,6 @@
5288
</div>
5289
</div>
5290
<div id="hiddenDownloadLinks" style="display: none;" hidden></div>
5291
- <script type="text/javascript" src="dashboard.js?v20171118-1"></script>
5291
+ <script type="text/javascript" src="dashboard.js?v20171118-2"></script>
5292
</body>
5293
</html>