@cryptotaxi247 / netdata-1 / commits / 3e226bd1b

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>