@millistream/millistream-widgets 1.0.23 → 1.0.24

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/millistream-widgets.js +523 -471
  2. package/package.json +1 -1
@@ -1,24 +1,24 @@
1
-
2
-
3
-
4
-
5
-
6
-
7
-
8
-
9
- (function(prototype) {
1
+ /**
2
+ * HiDPI Canvas Polyfill (1.0.10)
3
+ *
4
+ * Author: Jonathan D. Johnson (http://jondavidjohn.com)
5
+ * Homepage: https://github.com/jondavidjohn/hidpi-canvas-polyfill
6
+ * Issue Tracker: https://github.com/jondavidjohn/hidpi-canvas-polyfill/issues
7
+ * License: Apache-2.0
8
+ */
9
+ (function(prototype) {
10
10
 
11
11
  var pixelRatio = (function() {
12
12
  var canvas = document.createElement('canvas'),
13
13
  context = canvas.getContext('2d');
14
-
15
-
16
-
17
-
18
-
19
-
20
-
21
-
14
+ /*backingStore = context.backingStorePixelRatio ||
15
+ context.webkitBackingStorePixelRatio ||
16
+ context.mozBackingStorePixelRatio ||
17
+ context.msBackingStorePixelRatio ||
18
+ context.oBackingStorePixelRatio ||
19
+ context.backingStorePixelRatio || 1;
20
+ return (window.devicePixelRatio || 1) / backingStore;
21
+ */
22
22
  })(),
23
23
  forEach = function(obj, func) {
24
24
  for (var p in obj) {
@@ -29,8 +29,8 @@
29
29
  },
30
30
 
31
31
  ratioArgs = {
32
-
33
-
32
+ //'fillRect': 'all',
33
+ //'clearRect': 'all',
34
34
  'strokeRect': 'all',
35
35
  'moveTo': 'all',
36
36
  'lineTo': 'all',
@@ -43,18 +43,18 @@
43
43
  'rect': 'all',
44
44
  'translate': 'all',
45
45
  'createRadialGradient': 'all',
46
-
46
+ //'createLinearGradient': 'all'
47
47
  };
48
48
 
49
49
  if (pixelRatio === 1) return;
50
50
 
51
51
  function getPixelRatio(_this) {
52
-
53
-
54
-
55
-
56
-
57
-
52
+ /* var backingStore = this.backingStorePixelRatio ||
53
+ this.webkitBackingStorePixelRatio ||
54
+ this.mozBackingStorePixelRatio ||
55
+ this.msBackingStorePixelRatio ||
56
+ this.oBackingStorePixelRatio ||
57
+ this.backingStorePixelRatio || 1;*/
58
58
  var backingStore = _this.backingStorePixelRatio ||
59
59
  _this.webkitBackingStorePixelRatio ||
60
60
  _this.mozBackingStorePixelRatio ||
@@ -63,14 +63,14 @@
63
63
  _this.backingStorePixelRatio || 1;
64
64
  return (window.devicePixelRatio || 1) / backingStore;
65
65
 
66
- };
66
+ }
67
67
 
68
68
  forEach(ratioArgs, function(value, key) {
69
69
  prototype[key] = (function(_super) {
70
70
  return function() {
71
71
  var i, len,
72
72
  args = Array.prototype.slice.call(arguments);
73
- if (key == 'lineTo' || key == 'moveTo') {
73
+ if (key == 'lineTo' || key == 'moveTo') { // PF
74
74
  args = args.map(function(a) {
75
75
  return a;
76
76
  });
@@ -90,7 +90,7 @@
90
90
  })(prototype[key]);
91
91
  });
92
92
 
93
-
93
+ // Stroke lineWidth adjustment
94
94
  prototype.stroke = (function(_super) {
95
95
  return function() {
96
96
  this.lineWidth *= getPixelRatio(this);
@@ -114,12 +114,12 @@
114
114
  var i = _super.apply(this, args);
115
115
 
116
116
  this.font = tmp;
117
-
118
-
119
-
120
-
121
-
122
-
117
+ /*this.font = this.font.replace(
118
+ /(\d+)(px|em|rem|pt)/g,
119
+ function(w, m, u) {
120
+ return Math.floor(m / getPixelRatio()) + u;
121
+ }
122
+ );*/
123
123
  return i;
124
124
  };
125
125
  })(prototype.measureText);
@@ -145,8 +145,8 @@
145
145
  return function() {
146
146
  var args = Array.prototype.slice.call(arguments);
147
147
 
148
- args[1] *= getPixelRatio(this);
149
- args[2] *= getPixelRatio(this);
148
+ args[1] *= getPixelRatio(this); // x
149
+ args[2] *= getPixelRatio(this); // y
150
150
  var tmp = this.font;
151
151
  var _this = this;
152
152
  this.font = this.font.replace(
@@ -158,12 +158,12 @@
158
158
 
159
159
  _super.apply(this, args);
160
160
  this.font = tmp;
161
-
162
-
163
-
164
-
165
-
166
-
161
+ /*this.font = this.font.replace(
162
+ /(\d+)(px|em|rem|pt)/g,
163
+ function(w, m, u) {
164
+ return (m / getPixelRatio()) + u;
165
+ }
166
+ );*/
167
167
  };
168
168
  })(prototype.strokeText);
169
169
 
@@ -185,17 +185,17 @@
185
185
  }
186
186
  prototype.getContext = (function(_super) {
187
187
  return function(type) {
188
-
188
+ //var backingStore, ratio;
189
189
  context = _super.call(this, type);
190
190
 
191
191
  if (type === '2d') {
192
192
 
193
-
194
-
195
-
196
-
197
-
198
-
193
+ /*backingStore = context.backingStorePixelRatio ||
194
+ context.webkitBackingStorePixelRatio ||
195
+ context.mozBackingStorePixelRatio ||
196
+ context.msBackingStorePixelRatio ||
197
+ context.oBackingStorePixelRatio ||
198
+ context.backingStorePixelRatio || 1;*/
199
199
 
200
200
  var ratio = getPixelRatio();
201
201
  if (ratio > 1) {
@@ -220,7 +220,7 @@
220
220
 
221
221
  })(HTMLCanvasElement.prototype);
222
222
 
223
-
223
+ // Millistream Chart
224
224
  function Milli_Chart(settings) {
225
225
  "use strict";
226
226
  var _this = this;
@@ -242,13 +242,13 @@ function Milli_Chart(settings) {
242
242
  compress: 1,
243
243
  curveOnTop: true,
244
244
  dateformat: 'd/m',
245
- drawxaxis: true,
245
+ drawxaxis: true, // TODO: 0 no, 1 yes, 2 yeas with markers (3px lines)
246
246
  drawyaxis: true,
247
247
  drawy2axis: false,
248
248
  enablezoom: true,
249
249
  fields: ['name', 'tradecurrency', 'time', 'date', 'tradeprice', 'tradequantity', 'marketopen', 'marketclose'],
250
250
  fillchart: false,
251
- gridVerticalLines: true,
251
+ gridVerticalLines: true, // 0 off, 1 draw grid lines ,2 fillrect modulo
252
252
  gridVerticalLinesStyle: 'line',
253
253
  gridHorizontalLines: true,
254
254
  gridHorizontalLinesStyle: 'dash',
@@ -257,7 +257,7 @@ function Milli_Chart(settings) {
257
257
  instrument: null,
258
258
  intradayDatePos: { x: 'center', y: 'bottom', orientation: 'horizontal', dateformat: 'd mmm' },
259
259
  intradaylen: null,
260
- messagetypes: 1030,
260
+ messagetypes: 1030, // quote,trades and performance
261
261
  nochartlabel: 'No data to draw on',
262
262
  onreadyCallback: null,
263
263
  previousDayClose: true,
@@ -272,8 +272,8 @@ function Milli_Chart(settings) {
272
272
  display: 'block'
273
273
  },
274
274
  xAxisSpacing: 0,
275
- yAxisSpacing: 4,
276
- xAxisModulo: 1
275
+ yAxisSpacing: 4, // undocumented
276
+ xAxisModulo: 1 // undocumented
277
277
  };
278
278
  var m_startdate = null;
279
279
  var m_chartspaces = {
@@ -286,10 +286,10 @@ function Milli_Chart(settings) {
286
286
  height: 0
287
287
  }
288
288
  };
289
- var m_dummyDiv = null;
289
+ var m_dummyDiv = null; // dummy div For chartclasses
290
290
  var m_canvas = null;
291
291
  var m_ctx = null;
292
- var m_datapoints = [];
292
+ var m_datapoints = []; // for mouseover
293
293
  var m_dataPoints = {
294
294
  arr: [],
295
295
  map: new Map()
@@ -378,7 +378,7 @@ function Milli_Chart(settings) {
378
378
  }
379
379
  var m_instrumentCss = [{
380
380
  color: '#E2507A',
381
-
381
+ //backgroundImage: 'linear-gradient(rgba(226, 80, 122, 0.6),rgba(226, 80, 122, 0))',
382
382
  width: 1
383
383
  }, {
384
384
  color: '#ff0000',
@@ -427,10 +427,10 @@ function Milli_Chart(settings) {
427
427
  }
428
428
 
429
429
  function dateDiffInDays(a, b) {
430
-
430
+ // Discard the time and time-zone information.
431
431
  const utc1 = Date.UTC(a.getFullYear(), a.getMonth(), a.getDate());
432
432
  const utc2 = Date.UTC(b.getFullYear(), b.getMonth(), b.getDate());
433
- return Math.floor((utc2 - utc1) / 86400000);
433
+ return Math.floor((utc2 - utc1) / 86400000); // ms per day
434
434
  }
435
435
 
436
436
  function findFirstWeekDay(date) {
@@ -444,7 +444,7 @@ function Milli_Chart(settings) {
444
444
  }
445
445
 
446
446
  function getFontSize(obj) {
447
-
447
+ //return parseInt(obj.fontSize) * window.devicePixelRatio;
448
448
  return parseInt(obj.fontSize);
449
449
  }
450
450
 
@@ -601,11 +601,23 @@ function Milli_Chart(settings) {
601
601
  _this.scaleinfoY.lowLowerChart = null;
602
602
  _this.scaleinfoY.highLowerChart = null;
603
603
  var data, i;
604
+ var useCloseprice = false;
605
+ var today = new Date().getTime();
606
+ today -= today % 86400000;
607
+ var lastTradeDate = new Date().getTime();
608
+ var todaysOpenTime = new Date(new Date().toISOString().substring(0, 10) + 'T' + _this.instruments[0].marketopen + 'Z').getTime();
609
+ if (typeof _this.instruments[0].trades !== 'undefined' && _this.instruments[0].trades.length > 0) {
610
+ lastTradeDate = new Date(_this.instruments[0].trades[_this.instruments[0].trades.length - 1].timestamp).getTime();
611
+ lastTradeDate -= lastTradeDate % 86400000;
612
+ }
613
+ var quote_timestamp = _this.instruments[0].quotedate + _this.instruments[0].quotetime;
614
+
615
+ if ((_this.instruments[0].quotedate == today && quote_timestamp > todaysOpenTime) || _this.instruments[0].quotedate == lastTradeDate) useCloseprice = true;
604
616
  for (var s = 0; s < _this.instruments.length; s++) {
605
617
  if (_this.instruments[s].insref == 0) continue;
606
618
  _this.instruments[s].startValue = null;
607
619
  data = _this.instruments[s][_this.scaleinfoY.type];
608
- if (_this.scaleinfoY.type != 'history') {
620
+ if (_this.scaleinfoY.type != 'history' && useCloseprice) {
609
621
  if ((_this.settings.chartlen == '1d' || _this.settings.chartlen == '0d') && !m_zoom.mousedown.timestamp) {
610
622
  _this.instruments[s].startValue = parseFloat(_this.instruments[s].closeprice1d) * _this.instruments[s].factor;
611
623
  }
@@ -613,7 +625,7 @@ function Milli_Chart(settings) {
613
625
  var quantity = 0;
614
626
 
615
627
  for (i = 0; i < data.length; i++) {
616
-
628
+ // only calc on visible data
617
629
  var price = data[i].price * _this.instruments[s].factor;
618
630
  quantity = 0;
619
631
  if (data[i].quantity !== 'undefined') {
@@ -621,7 +633,8 @@ function Milli_Chart(settings) {
621
633
  }
622
634
  if (data[i].timestamp < _this.scaleinfoX.startTimeStamp) {
623
635
  if (_this.scaleinfoY.type == 'history') _this.instruments[s].startValue = price;
624
- else if (_this.settings.chartlen != '1d' && _this.settings.chartlen != '0d' && !m_zoom.mousedown.timestamp) {
636
+ //else if (_this.settings.chartlen != '1d' && _this.settings.chartlen != '0d' && !m_zoom.mousedown.timestamp) {
637
+ else if (useCloseprice == false || m_zoom.mousedown.timestamp) {
625
638
  _this.instruments[s].startValue = price;
626
639
  }
627
640
  continue;
@@ -631,7 +644,7 @@ function Milli_Chart(settings) {
631
644
  }
632
645
 
633
646
  if (_this.scaleinfoY.type != 'history' && (data[i].timestamp % 86400000 < _this.instruments[0].opentimestamp || data[i].timestamp % 86400000 > _this.instruments[0].closetimestamp)) {
634
-
647
+ // stämmer detta kan det bli överlapp vid sommartid/vintertid?
635
648
  continue;
636
649
  }
637
650
 
@@ -658,7 +671,7 @@ function Milli_Chart(settings) {
658
671
  if (_this.scaleinfoY.lowLowerChart == null || _this.scaleinfoY.lowLowerChart > quantity) _this.scaleinfoY.lowLowerChart = quantity;
659
672
  if (_this.scaleinfoY.highLowerChart == null || _this.scaleinfoY.highLowerChart < quantity) _this.scaleinfoY.highLowerChart = quantity;
660
673
  }
661
- if ((_this.settings.chartlen == '1d' || _this.settings.chartlen == '0d') && !m_zoom.mousedown.timestamp) {
674
+ if ((_this.settings.chartlen == '1d' || _this.settings.chartlen == '0d') && !m_zoom.mousedown.timestamp) { // if closeprice is used calch high/low on it
662
675
  var cp = parseFloat(_this.instruments[s].closeprice1d) * _this.instruments[s].factor;
663
676
  if (_this.scaleinfoY.lowValue > cp) _this.scaleinfoY.lowValue = cp;
664
677
  else
@@ -687,11 +700,11 @@ function Milli_Chart(settings) {
687
700
  _this.scaleinfoY.lowValue -= 1;
688
701
  _this.scaleinfoY.highValue += 1;
689
702
  }
690
-
703
+ // do we have any analyzis we need to take into account
691
704
  for (i = 0; i < _this.settings.indicators.length; i++) {
692
705
  if (_this.scaleinfoY.type == 'history') data = _this.settings.indicators[i].history;
693
706
  else data = _this.settings.indicators[i].trades;
694
- for (var s = 0; s < data.length; s++) {
707
+ for (s = 0; s < data.length; s++) {
695
708
  if (data[s].timestamp < _this.scaleinfoX.startTimeStamp) {
696
709
  continue;
697
710
  }
@@ -707,38 +720,11 @@ function Milli_Chart(settings) {
707
720
  }
708
721
  }
709
722
  }
723
+ _this.scaleinfoY2.lowValue = (_this.scaleinfoY.lowValue - _this.instruments[0].startValue) / _this.instruments[0].startValue * 100;
724
+ _this.scaleinfoY2.highValue = (_this.scaleinfoY.highValue - _this.instruments[0].startValue) / _this.instruments[0].startValue * 100;
710
725
  return 1;
711
726
  }
712
727
 
713
- function plotLower(valuePerPixel, lineLength) {
714
- m_ctx.save();
715
- m_ctx.strokeStyle = m_instrumentCss[0].color;
716
- m_ctx.lineWidth = m_instrumentCss[0].width;
717
- var width = Math.round(m_chartspaces.lowerChart.width / (m_datapoints.length + 1) / 2);
718
- if (width < 2) width = 2;
719
- else if (width > 20) width = 20;
720
- m_ctx.lineWidth = width;
721
- for (var i = 0; i < m_datapoints.length; i++) {
722
- var x = m_datapoints[i].x + 0.5;
723
- m_ctx.lineWidth = width;
724
- if (x - width <= m_chartspaces.lowerChart.left) {
725
- m_ctx.lineWidth = width / 2;
726
- x += m_ctx.lineWidth / 2;
727
- } else
728
- if (x + width >= m_chartspaces.lowerChart.right) {
729
- m_ctx.lineWidth = width / 2;
730
- x -= m_ctx.lineWidth / 2 + 1;
731
- }
732
- m_ctx.beginPath();
733
- m_ctx.moveTo(x, m_chartspaces.lowerChart.bottom - 0.5);
734
- var y = Math.round(m_chartspaces.lowerChart.bottom - (m_datapoints[i].quantity * valuePerPixel)) - 1;
735
- m_ctx.closePath();
736
- m_ctx.lineTo(x, y - 0.5);
737
- m_ctx.stroke();
738
- }
739
- m_ctx.restore();
740
- }
741
-
742
728
  function drawYLegendLower(x, numticks, lineLength, markers) {
743
729
  var i;
744
730
  _this.scaleinfoY.lowLowerChart = null;
@@ -760,7 +746,7 @@ function Milli_Chart(settings) {
760
746
  var maxValue = _this.scaleinfoY.highLowerChart == 0 ? 100 : _this.scaleinfoY.highLowerChart + (tickSize * 0.2);
761
747
  var valuePerPixel = lineLength / maxValue;
762
748
  if (isNaN(valuePerPixel) || !isFinite(valuePerPixel)) {
763
- () => {};
749
+ console.log('cant draw valuePerPixel' + valuePerPixel, lineLength, maxValue);
764
750
  return false;
765
751
  }
766
752
  var value = 0;
@@ -781,7 +767,7 @@ function Milli_Chart(settings) {
781
767
  m_ctx.closePath();
782
768
  m_ctx.restore();
783
769
  } else
784
- if (_this.settings.drawyaxis == true && markers == true) {
770
+ if (_this.settings.drawyaxis == true && markers == true) { // draw legenditem markers for price
785
771
  m_ctx.beginPath();
786
772
  m_ctx.moveTo(m_chartspaces.lowerChart.left, y + 0.5);
787
773
  m_ctx.lineTo(m_chartspaces.lowerChart.left + 3, y + 0.5);
@@ -793,7 +779,7 @@ function Milli_Chart(settings) {
793
779
  var label = formatLargeNumber(value, 0, _this);
794
780
  var textpos = x - 5;
795
781
  if (m_yLegendCss.verticalAlign == 'top') {
796
- if (y - (getFontSize(m_yLegendCss)) > 0)
782
+ if (y - (getFontSize(m_yLegendCss)) > 0) // dont draw if cropped
797
783
  m_ctx.fillText(label, textpos, y - ((getFontSize(m_yLegendCss) + 2)));
798
784
  } else
799
785
  m_ctx.fillText(label, textpos, y - (getFontSize(m_yLegendCss) / 2));
@@ -811,7 +797,7 @@ function Milli_Chart(settings) {
811
797
  m_ctx.fillStyle = m_yLegendCss.color;
812
798
  var lineLen = m_chartspaces.lowerChart.bottom - m_chartspaces.lowerChart.top;
813
799
  var numticks = lineLen / (getFontSize(m_yLegendCss) * 2);
814
- if (numticks > 8) numticks = 8;
800
+ if (numticks > 8) numticks = 8; // limit to 8 items on Y legend ( this is not an absolut count, since we calculate nice legend numbers
815
801
 
816
802
  m_ctx.beginPath();
817
803
  m_ctx.strokeStyle = m_gridVerticalCss.color;
@@ -825,21 +811,22 @@ function Milli_Chart(settings) {
825
811
  }
826
812
 
827
813
  function checkYLegendSpace(y, text) {
828
-
814
+ //if (y - (getFontSize(m_yLegendCss) / 2) - m_chartspaces.chart.top < 0) return false;
829
815
  if (y - (getFontSize(m_yLegendCss)) - m_chartspaces.chart.top < 0) return false;
830
816
  if (y > m_chartspaces.chart.bottom) return false;
831
817
  return true;
832
818
  }
833
819
 
834
- function drawY2Legend(x) {
820
+ function drawY2Legend(x) { // percent
821
+ if (_this.instruments[0].pricetype == 'yield') return;
835
822
  if (_this.settings.absoluteScaling == true) {
836
823
  for (var s = 1; s < _this.instruments.length; s++) {
837
824
  if (_this.instruments[s].insref != 0) return;
838
825
  }
839
826
  }
840
- if (_this.instruments[0].startValue == null || (_this.scaleinfoY2.highValue == 100 && _this.scaleinfoY2.lowValue == 0)) return false;
827
+
841
828
  _this.scaleinfoY2.maxValue = _this.scaleinfoY2.highValue + (_this.scaleinfoY2.tickSize * 0.2);
842
- _this.scaleinfoY2.minValue = _this.scaleinfoY2.lowValue + (_this.scaleinfoY2.tickSize * 0.2);
829
+ _this.scaleinfoY2.minValue = _this.scaleinfoY2.lowValue - (_this.scaleinfoY2.tickSize * 0.2);
843
830
  m_ctx.font = m_y2LegendCss.fontWeight + ' ' + m_y2LegendCss.fontSize + ' ' + m_y2LegendCss.fontFamily;
844
831
  var value;
845
832
  if (_this.scaleinfoY2.highValue == _this.scaleinfoY2.lowValue) {
@@ -859,7 +846,7 @@ function Milli_Chart(settings) {
859
846
  var count = 0;
860
847
  for (;;) {
861
848
  if (count++ > 10) {
862
- () => {};
849
+ console.log('break out');
863
850
  break;
864
851
  }
865
852
  var v;
@@ -870,9 +857,9 @@ function Milli_Chart(settings) {
870
857
  var y = Math.round(m_chartspaces.chart.height - getScaledSetting(m_chartCss.marginBottom) - ((v - _this.scaleinfoY.minValue) * _this.scaleinfoY.valuePerPixel));
871
858
 
872
859
  if (y <= m_chartspaces.chart.top) break;
873
-
860
+ //if (y > m_chartspaces.chart.bottom) break;
874
861
  if (y <= m_chartspaces.chart.bottom) {
875
- if (_this.settings.drawy2axis == true) {
862
+ if (_this.settings.drawy2axis == true) { // draw legenditem markers for diff
876
863
  m_ctx.beginPath();
877
864
  m_ctx.moveTo(x, y + 0.5);
878
865
  if ((m_y2LegendCss.float == 'left' && m_y2LegendCss.textAlign == 'left') || (m_y2LegendCss.float == 'right' && m_y2LegendCss.textAlign == 'left')) {
@@ -902,10 +889,16 @@ function Milli_Chart(settings) {
902
889
 
903
890
  function drawYLegend(si, x, gridHorizontalLines, number, draw) {
904
891
  var value;
905
- si.maxValue = si.highValue + (si.tickSize * 0.2);
906
- si.minValue = si.lowValue - (si.tickSize * 0.2);
892
+ //si.maxValue = si.highValue + (si.tickSize * 0.2);
893
+ //si.minValue = si.lowValue - (si.tickSize * 0.2);
894
+
895
+ let v = (si.highValue - si.lowValue) / si.lineLength;
896
+ si.maxValue = si.highValue + (v * parseInt(m_yLegendCss.fontSize));
897
+ si.minValue = si.lowValue - (v * parseInt(m_yLegendCss.fontSize));
898
+
899
+
907
900
  m_ctx.font = m_yLegendCss.fontWeight + ' ' + m_yLegendCss.fontSize + ' ' + m_yLegendCss.fontFamily;
908
- if (si.highValue == si.lowValue) {
901
+ if (si.highValue == si.lowValue) { // only have one value so set values for 1 line only
909
902
  si.maxValue = si.maxValue + si.tickSize;
910
903
  si.minValue = si.minValue - si.tickSize;
911
904
  value = Math.abs(si.lowValue);
@@ -917,14 +910,14 @@ function Milli_Chart(settings) {
917
910
  }
918
911
  si.valuePerPixel = si.lineLength / (si.maxValue - si.minValue);
919
912
  if (isNaN(si.valuePerPixel) || !isFinite(si.valuePerPixel)) {
920
- () => {};
913
+ console.log('cant draw valuePerPixel', si.valuePerPixel, si.lineLength, si.maxValue, si.minValue);
921
914
  return false;
922
915
  }
923
916
  var textpos;
924
917
  var count = 0;
925
918
  for (;;) {
926
919
  if (count++ > 10) {
927
- () => {};
920
+ console.log('failsafe break');
928
921
  break;
929
922
  }
930
923
  var y = Math.round(m_chartspaces.chart.height - getScaledSetting(m_chartCss.marginBottom) - ((value - si.minValue) * si.valuePerPixel));
@@ -948,7 +941,7 @@ function Milli_Chart(settings) {
948
941
  }
949
942
 
950
943
  } else
951
- if (_this.settings.drawyaxis == true && number == 1 && draw) {
944
+ if (_this.settings.drawyaxis == true && number == 1 && draw) { // draw legenditem markers for price
952
945
  if (!draw) return;
953
946
  m_ctx.beginPath();
954
947
  m_ctx.moveTo(m_chartspaces.chart.left, y + 0.5);
@@ -986,48 +979,49 @@ function Milli_Chart(settings) {
986
979
  m_ctx.fillStyle = m_yLegendCss.color;
987
980
  if (0 == calcHighLow()) {
988
981
  m_ctx.restore();
989
- () => {};
982
+ console.log('fail highlow');
990
983
  return;
991
984
  }
992
985
  _this.scaleinfoY.lineLength = m_chartspaces.chart.bottom - m_chartspaces.chart.top;
993
986
  _this.scaleinfoY2.lineLength = _this.scaleinfoY.lineLength;
994
-
987
+ //var numticks = (_this.scaleinfoY.lineLength / window.devicePixelRatio) / (getFontSize(m_yLegendCss) * _this.settings.yAxisSpacing);
995
988
  var numticks = _this.scaleinfoY.lineLength / (getFontSize(m_yLegendCss) * _this.settings.yAxisSpacing);
996
- if (numticks > 8) numticks = 8;
989
+ if (numticks > 8) numticks = 8; // limit to 8 items on Y legend ( this is not an absolut count, since we calculate nice legend numbers
997
990
  _this.scaleinfoY.tickSize = getTickValue(_this.scaleinfoY.lowValue, _this.scaleinfoY.highValue, numticks);
998
- _this.scaleinfoY.decimals = _this.scaleinfoY.tickSize.countDecimals();
991
+ _this.scaleinfoY.decimals = _this.scaleinfoY.tickSize.countDecimals(); // räkna på diffen mellan high low kanske?
999
992
  _this.scaleinfoY.decimals = _this.scaleinfoY.decimals > 4 ? 4 : _this.scaleinfoY.decimals;
1000
993
  _this.scaleinfoY.decimals = _this.scaleinfoY.decimals < 2 ? 2 : _this.scaleinfoY.decimals;
1001
994
  var label = formatNiceNumber(_this.scaleinfoY.highValue, _this.settings.thousandseparator, _this.settings.decimalseparator, _this.scaleinfoY.decimals);
1002
995
  if (_this.settings.drawyaxis) {
1003
996
  if (m_yLegendCss.float != 'right') {
1004
- m_chartspaces.chart.left = 10 + Math.round(m_ctx.measureText(label).width);
997
+ m_chartspaces.chart.left = 10 + Math.round(m_ctx.measureText(label).width); // + 'px'; // räkna fram hur hur mycket plats Y värdena tar och sätt margin till det, skall vi göra så?
1005
998
  m_chartspaces.lowerChart.left = m_chartspaces.chart.left;
1006
999
  } else {
1007
1000
  if (m_yLegendCss.textAlign == 'right') {
1008
- m_chartspaces.chart.right = m_canvas.width - (10 + Math.round(m_ctx.measureText(label).width));
1001
+ m_chartspaces.chart.right = m_canvas.width - (10 + Math.round(m_ctx.measureText(label).width)); // + 'px'; // räkna fram hur hur mycket plats Y värdena tar och sätt margin till det, skall vi göra så?
1009
1002
  m_chartspaces.lowerChart.right = m_chartspaces.chart.right;
1010
1003
  }
1011
1004
  }
1012
1005
  }
1013
- if (_this.settings.drawy2axis) {
1014
-
1006
+ if (_this.settings.drawy2axis) { // calc space for y2
1007
+ //var numticks = _this.scaleinfoY2.lineLength / (getFontSize(m_yLegendCss) * _this.settings.yAxisSpacing);
1015
1008
  _this.scaleinfoY2.tickSize = getTickValue(_this.scaleinfoY2.lowValue, _this.scaleinfoY2.highValue, numticks);
1016
1009
 
1017
- _this.scaleinfoY2.decimals = _this.scaleinfoY2.tickSize.countDecimals();
1010
+ _this.scaleinfoY2.decimals = _this.scaleinfoY2.tickSize.countDecimals(); // räkna på diffen mellan high low kanske?
1018
1011
  _this.scaleinfoY2.decimals = _this.scaleinfoY2.decimals > 4 ? 4 : _this.scaleinfoY2.decimals;
1019
1012
  _this.scaleinfoY2.decimals = _this.scaleinfoY2.decimals < 0 ? 0 : _this.scaleinfoY2.decimals;
1020
1013
 
1021
1014
  var widestDiff = '-' + Math.max(Math.abs(_this.scaleinfoY2.highValue), Math.abs(_this.scaleinfoY2.lowValue));
1022
- label = formatNiceNumber(widestDiff, _this.settings.thousandseparator, _this.settings.decimalseparator, _this.scaleinfoY2.decimals) + ' %';
1015
+ if (_this.settings.priceIndicator == false) label = formatNiceNumber(widestDiff, _this.settings.thousandseparator, _this.settings.decimalseparator, _this.scaleinfoY2.decimals) + ' %';
1016
+ else label = formatNiceNumber(widestDiff, _this.settings.thousandseparator, _this.settings.decimalseparator, _this.scaleinfoY2.decimals < 2 ? 2 : _this.scaleinfoY2.decimals) + ' %'; // priceIndicator has 2 decimals
1023
1017
  if (m_y2LegendCss.float != 'right') {
1024
1018
  if (m_y2LegendCss.textAlign == 'left')
1025
- m_chartspaces.chart.left = 10 + Math.round(m_ctx.measureText(label).width);
1019
+ m_chartspaces.chart.left = 10 + Math.round(m_ctx.measureText(label).width); // + 'px'; // räkna fram hur hur mycket plats Y värdena tar och sätt margin till det, skall vi göra så?
1026
1020
  m_chartspaces.lowerChart.left = m_chartspaces.chart.left;
1027
1021
  } else {
1028
-
1022
+ // kolla setting om den skall vara "i diagrammet"
1029
1023
  if (m_y2LegendCss.textAlign == 'right')
1030
- m_chartspaces.chart.right = m_canvas.width - (10 + Math.round(m_ctx.measureText(label).width));
1024
+ m_chartspaces.chart.right = m_canvas.width - (10 + Math.round(m_ctx.measureText(label).width)); // + 'px'; // räkna fram hur hur mycket plats Y värdena tar och sätt margin till det, skall vi göra så?
1031
1025
  m_chartspaces.lowerChart.right = m_chartspaces.chart.right;
1032
1026
  }
1033
1027
  }
@@ -1075,7 +1069,7 @@ function Milli_Chart(settings) {
1075
1069
  }
1076
1070
 
1077
1071
  function drawXAxisGridlines(p, newday) {
1078
-
1072
+ // draws the vertical grid or dots
1079
1073
  m_ctx.save();
1080
1074
  m_ctx.strokeStyle = m_gridVerticalCss.color;
1081
1075
  if (_this.settings.gridVerticalLines) {
@@ -1098,7 +1092,7 @@ function Milli_Chart(settings) {
1098
1092
  m_ctx.closePath();
1099
1093
  }
1100
1094
  } else
1101
- if (_this.settings.drawxaxis != 0) {
1095
+ if (_this.settings.drawxaxis != 0) { // if no grid but drawxaxis , add markers for date/time
1102
1096
  m_ctx.beginPath();
1103
1097
  m_ctx.moveTo(p.x + 0.5, p.y);
1104
1098
  m_ctx.lineTo(p.x + 0.5, p.y + 3);
@@ -1109,13 +1103,13 @@ function Milli_Chart(settings) {
1109
1103
  }
1110
1104
 
1111
1105
  function calcXScale(starttime, endtime) {
1112
-
1106
+ // vad är detta?
1113
1107
  _this.scaleinfoX.startDate = new Date(starttime);
1114
1108
  _this.scaleinfoX.endDate = new Date(endtime);
1115
1109
  _this.scaleinfoX.days = getNumberOfDays(starttime, endtime);
1116
1110
  _this.scaleinfoX.lineLength = m_chartspaces.chart.right - m_chartspaces.chart.left;
1117
- var datesize = new Date('2888-12-28');
1118
- _this.scaleinfoX.itemwidth = getStringWidth(m_ctx, formatDate(datesize, _this.settings.dateformat, _this)) * 2;
1111
+ var datesize = new Date('2888-12-28'); // bredaste datum jag kan komma på
1112
+ _this.scaleinfoX.itemwidth = getStringWidth(m_ctx, formatDate(datesize, _this.settings.dateformat, _this)) * 2; // kolla rätt format en 8a för varje tecken
1119
1113
 
1120
1114
  var maxLegendItems = _this.scaleinfoX.lineLength / (_this.scaleinfoX.itemwidth * 2);
1121
1115
 
@@ -1137,7 +1131,7 @@ function Milli_Chart(settings) {
1137
1131
  var tmp = 60;
1138
1132
  while (tmp < x) {
1139
1133
  tmp += 60;
1140
- if (x - tmp < 20) break;
1134
+ if (x - tmp < 20) break; // if less than 20 mins to next hour breakout
1141
1135
  }
1142
1136
  _this.scaleinfoX.ticksize = tmp * 60000;
1143
1137
  }
@@ -1145,22 +1139,22 @@ function Milli_Chart(settings) {
1145
1139
  }
1146
1140
 
1147
1141
  function getXPosition(timestamp) {
1148
- var offset = (timestamp.getTime() - _this.scaleinfoX.startDate.getTime()) / (86400000 * 7);
1142
+ var offset = (timestamp.getTime() - _this.scaleinfoX.startDate.getTime()) / (86400000 * 7); // veckor
1149
1143
  offset = offset * 86400000 * 2 / _this.scaleinfoX.timePerPixel;
1150
1144
  return Math.round(m_chartspaces.chart.left + ((timestamp.getTime() - _this.scaleinfoX.startDate.getTime()) / _this.scaleinfoX.timePerPixel) - offset);
1151
1145
  }
1152
1146
 
1153
1147
  function checkXLegendSides(x, text) {
1154
-
1148
+ // right
1155
1149
  if (_this.scaleinfoX.lineLength + m_chartspaces.chart.left < x + (m_ctx.measureText(text).width / 2)) return false;
1156
-
1150
+ // left
1157
1151
  if (m_chartspaces.chart.left > x - (m_ctx.measureText(text).width / 2)) return false;
1158
1152
  return true;
1159
1153
 
1160
1154
  }
1161
1155
 
1162
1156
  function drawXAxisYears(starttime, endtime) {
1163
- if (getNumberOfDays(starttime, endtime) < 250) return drawXAxisMonth(starttime, endtime);
1157
+ if (getNumberOfDays(starttime, endtime) < 250) return drawXAxisMonth(starttime, endtime); // exchange days
1164
1158
  m_ctx.save();
1165
1159
  m_ctx.font = m_xLegendCss.fontWeight + ' ' + m_xLegendCss.fontSize + ' ' + m_xLegendCss.fontFamily;
1166
1160
  m_ctx.strokeStyle = m_gridHorizontalCss.color;
@@ -1176,7 +1170,7 @@ function Milli_Chart(settings) {
1176
1170
  }
1177
1171
  m_ctx.strokeStyle = m_gridVerticalCss.color;
1178
1172
  var legendItems = [];
1179
-
1173
+ // draw Years
1180
1174
  var year = _this.scaleinfoX.startDate.getFullYear() + 1;
1181
1175
  var numItems = 0,
1182
1176
  x, draw, i, text;
@@ -1193,7 +1187,7 @@ function Milli_Chart(settings) {
1193
1187
  text = year;
1194
1188
  if (checkXLegendSides(x, text)) {
1195
1189
  if (_this.settings.yearLabelsPos == 'top') {
1196
- m_ctx.save();
1190
+ m_ctx.save(); // flip and write new years on top
1197
1191
  var fontMetrix = m_ctx.measureText(text);
1198
1192
  x = x + fontMetrix.actualBoundingBoxAscent + fontMetrix.actualBoundingBoxDescent + 2;
1199
1193
  var y = m_chartspaces.chart.top;
@@ -1210,14 +1204,14 @@ function Milli_Chart(settings) {
1210
1204
  }
1211
1205
  year++;
1212
1206
  }
1213
- if (numItems * m_ctx.measureText('8888').width / _this.scaleinfoX.lineLength > 0.3) numItems = 11;
1214
-
1215
- if (numItems < 10) {
1207
+ if (numItems * m_ctx.measureText('8888').width / _this.scaleinfoX.lineLength > 0.3) numItems = 11; // keep it clean
1208
+ // draw half year
1209
+ if (numItems < 10) { // max 10 items här för att skriva halvår
1216
1210
  year = new Date(_this.scaleinfoX.startDate.getFullYear() + '-07-01T00:00:00Z');
1217
1211
  if (year.getTime() < _this.scaleinfoX.startDate.getTime())
1218
1212
  year = new Date(_this.scaleinfoX.startDate.getFullYear() + 1 + '-07-01T00:00:00Z');
1219
1213
  while (year < _this.scaleinfoX.endDate) {
1220
- x = getXPosition(new Date(year.getFullYear() + '-07-01T00:00:00Z'));
1214
+ x = getXPosition(new Date(year.getFullYear() + '-07-01T00:00:00Z')); // 7
1221
1215
  draw = true;
1222
1216
  for (i = 0; i < legendItems.length; i++) {
1223
1217
  if (Math.abs(legendItems[i].x - x) < getMaxDateWidth()) {
@@ -1236,13 +1230,13 @@ function Milli_Chart(settings) {
1236
1230
  year = new Date((year.getFullYear() + 1) + '-07-01T00:00:00Z');
1237
1231
  }
1238
1232
  }
1239
-
1240
- if (numItems * m_ctx.measureText('8888').width / _this.scaleinfoX.lineLength > 0.3) numItems = 11;
1241
- if (numItems < 10) {
1233
+ // draw Quarter
1234
+ if (numItems * m_ctx.measureText('8888').width / _this.scaleinfoX.lineLength > 0.3) numItems = 11; // keep it clean
1235
+ if (numItems < 10) { // max 10 items här för att skriva kvartal
1242
1236
  year = new Date(_this.scaleinfoX.startDate.getFullYear() + '-04-01T00:00:00Z');
1243
1237
  if (year.getTime() < _this.scaleinfoX.startDate.getTime())
1244
1238
  year = new Date(_this.scaleinfoX.startDate.getFullYear() + 1 + '-04-01T00:00:00Z');
1245
- var dontPrint = false;
1239
+ var dontPrint = false; // if no space for first quarter dont print second either
1246
1240
  while (year < _this.scaleinfoX.endDate) {
1247
1241
  x = getXPosition(new Date(year.getFullYear() + '-04-01T00:00:00Z'));
1248
1242
  draw = true;
@@ -1263,7 +1257,7 @@ function Milli_Chart(settings) {
1263
1257
  legendItems.push({ 'text': text, timestamp: new Date(year + '-04-01T00:00:00Z'), 'x': x });
1264
1258
  year = new Date((year.getFullYear() + 1) + '-04-01T00:00:00Z');
1265
1259
  }
1266
-
1260
+ // Draw Quarter 2
1267
1261
  if (dontPrint == false) {
1268
1262
  year = new Date(_this.scaleinfoX.startDate.getFullYear() + '-10-01T00:00:00Z');
1269
1263
  if (year.getTime() < _this.scaleinfoX.startDate.getTime())
@@ -1300,7 +1294,7 @@ function Milli_Chart(settings) {
1300
1294
  m_ctx.strokeStyle = m_gridHorizontalCss.color;
1301
1295
  m_ctx.fillStyle = m_xLegendCss.color;
1302
1296
  calcXScale(starttime, endtime);
1303
- if (_this.settings.drawxaxis != 0) {
1297
+ if (_this.settings.drawxaxis != 0) { // draw line
1304
1298
  m_ctx.beginPath();
1305
1299
  m_ctx.moveTo(m_chartspaces.chart.left, m_chartspaces.chart.height - getScaledSetting(m_chartCss.marginBottom) + 0.5);
1306
1300
  m_ctx.lineTo(m_chartspaces.chart.right, m_chartspaces.chart.height - getScaledSetting(m_chartCss.marginBottom) + 0.5);
@@ -1315,14 +1309,14 @@ function Milli_Chart(settings) {
1315
1309
  var draw = true;
1316
1310
  var offset = 0;
1317
1311
  var count = 0;
1318
- while (currentDate.getTime() < _this.scaleinfoX.endTimeStamp) {
1312
+ while (currentDate.getTime() < _this.scaleinfoX.endTimeStamp) { // oklart om det skall vara så här 2021-06-01
1319
1313
  draw = true;
1320
- while (currentDate.getDay() == 0 || currentDate.getDay() == 6) {
1314
+ while (currentDate.getDay() == 0 || currentDate.getDay() == 6) { // move past weekends , maybe skip this if date is available in data
1321
1315
  currentDate = new Date(currentDate.getTime() + 86400000);
1322
1316
  offset += 86400000 / _this.scaleinfoX.timePerPixel;
1323
1317
  }
1324
1318
  x = Math.round(m_chartspaces.chart.left + ((currentDate.getTime() - _this.scaleinfoX.startDate.getTime()) / _this.scaleinfoX.timePerPixel) - offset);
1325
- if (lastx == 0 && m_chartspaces.chart.left > (x - (getMaxDateWidth() / 2))) {
1319
+ if (lastx == 0 && m_chartspaces.chart.left > (x - (getMaxDateWidth() / 2))) { // do not print left of y legend
1326
1320
  currentDate = new Date(currentDate.getTime() + 86400000);
1327
1321
  continue;
1328
1322
  }
@@ -1340,7 +1334,7 @@ function Milli_Chart(settings) {
1340
1334
  }
1341
1335
  currentDate = new Date(currentDate.getTime() + 86400000);
1342
1336
  }
1343
-
1337
+ // vad är detta?
1344
1338
  if (typeof m_chartCss.boxShadow !== 'undefined' && typeof m_chartCss.boxShadow.rightWidth !== 'undefined') {
1345
1339
  if (m_chartCss.boxShadow.rightWidth == 0) drawXAxisGridlines({ 'x': x, y: m_chartspaces.chart.bottom }, false);
1346
1340
  } else {
@@ -1352,9 +1346,9 @@ function Milli_Chart(settings) {
1352
1346
  function calcXScaleTick(starttime, endtime) {
1353
1347
  _this.scaleinfoX.startDate = new Date(starttime);
1354
1348
  _this.scaleinfoX.endDate = new Date(endtime);
1355
- _this.scaleinfoX.days = getNumberOfDays(starttime, endtime);
1356
- _this.scaleinfoX.lineLength = m_chartspaces.chart.right - m_chartspaces.chart.left;
1357
- _this.scaleinfoX.itemwidth = getStringWidth(m_ctx, '88:88') * 2;
1349
+ _this.scaleinfoX.days = getNumberOfDays(starttime, endtime); // kan vi nog skita i
1350
+ _this.scaleinfoX.lineLength = m_chartspaces.chart.right - m_chartspaces.chart.left;
1351
+ _this.scaleinfoX.itemwidth = getStringWidth(m_ctx, '88:88') * 2; // kolla rätt format en 8a för varje tecken
1358
1352
  var maxLegendItems = Math.floor(_this.scaleinfoX.lineLength / (_this.scaleinfoX.itemwidth * 2));
1359
1353
 
1360
1354
  if (_this.scaleinfoY.type != 'history') {
@@ -1381,38 +1375,41 @@ function Milli_Chart(settings) {
1381
1375
  for (i = 0; i < arr.length; i++) {
1382
1376
  pixelsperday[i] = arr[i] * timePerPixel;
1383
1377
  }
1384
- var x = totalmilli / maxLegendItems / 60000;
1378
+ //var x = totalmilli / maxLegendItems / 60000;
1385
1379
  var numticks = maxLegendItems;
1386
1380
 
1387
1381
  _this.scaleinfoX.milliPerDay = new Date('2019-01-01T' + _this.instruments[0].marketclose + 'Z') - new Date('2019-01-01T' + _this.instruments[0].marketopen + 'Z');
1388
1382
  _this.scaleinfoX.timePerPixel = timePerPixel;
1389
1383
 
1384
+ //_this.scaleinfoX.timePerPixel = (_this.scaleinfoX.milliPerDay * _this.scaleinfoX.days) / _this.scaleinfoX.lineLength;
1385
+
1386
+
1390
1387
  _this.scaleinfoX.tickPixelsPerDay = pixelsperday;
1391
1388
 
1392
1389
  var factor = 60;
1393
1390
  if (numticks < 1)
1394
- _this.scaleinfoX.ticksize = 86400000;
1391
+ _this.scaleinfoX.ticksize = 86400000; // öhh?
1395
1392
  else {
1396
1393
  if (numticks < 2) numticks = 2;
1397
- x = _this.scaleinfoX.milliPerDay / numticks / 60000;
1398
- if (totalmilli > 4 * 3600000) factor = 60;
1394
+ // x = _this.scaleinfoX.milliPerDay / numticks / 60000;
1395
+ if (totalmilli > 4 * 3600000) factor = 60; // 4 timmar
1399
1396
  else
1400
- if (totalmilli > 2 * 3600000) factor = 30;
1397
+ if (totalmilli > 2 * 3600000) factor = 30; // 2 timmar
1401
1398
  else
1402
- if (totalmilli > 3600000) factor = 20;
1399
+ if (totalmilli > 3600000) factor = 20; // 1 timma
1403
1400
  else
1404
- if (totalmilli > 3600000 / 2) factor = 10;
1401
+ if (totalmilli > 3600000 / 2) factor = 10; // 30 min
1405
1402
  else
1406
- if (totalmilli > 3600000 / 4) factor = 5;
1403
+ if (totalmilli > 3600000 / 4) factor = 5; // 15 min
1407
1404
  else factor = 1;
1408
- _this.scaleinfoX.ticksize = factor * 60000;
1405
+ _this.scaleinfoX.ticksize = factor * 60000; // time to add to next legenditem
1409
1406
  }
1410
1407
  return;
1411
1408
  }
1412
1409
  }
1413
1410
 
1414
1411
  function formatChartTime(value, format) {
1415
-
1412
+ // internal
1416
1413
  if (typeof value !== 'string') return "";
1417
1414
  var datetime = new Date();
1418
1415
  datetime.setHours(parseInt(value));
@@ -1471,7 +1468,7 @@ function Milli_Chart(settings) {
1471
1468
  m_ctx.fillStyle = m_xLegendCss.color;
1472
1469
  m_ctx.textAlign = "left";
1473
1470
  calcXScaleTick(starttime, endtime);
1474
- if (_this.settings.drawxaxis != 0) {
1471
+ if (_this.settings.drawxaxis != 0) { // draw line for legend
1475
1472
  m_ctx.beginPath();
1476
1473
  m_ctx.moveTo(m_chartspaces.chart.left, m_chartspaces.chart.bottom + 0.5);
1477
1474
  m_ctx.lineTo(m_chartspaces.chart.right, m_chartspaces.chart.bottom + 0.5);
@@ -1488,20 +1485,19 @@ function Milli_Chart(settings) {
1488
1485
  var legendItems = [];
1489
1486
  var openhour = new Date(new Date(currentDate.toISOString().substring(0, 10) + 'T' + _this.instruments[0].marketopen + 'Z')).getTime() % 86400000;
1490
1487
  var closehour = new Date(new Date(currentDate.toISOString().substring(0, 10) + 'T' + _this.instruments[0].marketclose + 'Z')).getTime() % 86400000;
1491
-
1488
+ // add daysstarts
1492
1489
  var middleOfDay = new Date(currentDate.getTime() - (currentDate.getTime() % 86400000) + ((openhour + closehour) / 2));
1493
1490
  if (_this.settings.intradayDatePos.x == 'left' && (_this.settings.intradayDatePos.y == 'scale' || _this.settings.intradayDatePos.y == 'top')) {
1494
1491
  middleOfDay = new Date(currentDate.getTime());
1495
1492
  }
1496
- if (currentDate.getTime() % 3600000 != 0)
1497
- currentDate = new Date(currentDate.getTime() - currentDate.getTime() % 3600000 + 3600000);
1498
-
1493
+ if (currentDate.getTime() % 3600000 != 0) // if not full hour, move up to next full hour
1494
+ currentDate = new Date(currentDate.getTime() - currentDate.getTime() % 3600000 + 3600000); // START om full hour (if modulo == 0 then + 3600000 kanske)
1499
1495
  var firstDate = new Date(currentDate);
1500
1496
  var days = calcTimeSpanInDays(starttime, endtime);
1501
1497
  if (m_zoom.mouseup.timestamp == null || (m_zoom.mouseup.timestamp != null && days > 1)) {
1502
1498
  while (currentDate.getTime() < _this.scaleinfoX.endTimeStamp) {
1503
1499
  draw = true;
1504
- while (currentDate.getDay() == 0 || currentDate.getDay() == 6) {
1500
+ while (currentDate.getDay() == 0 || currentDate.getDay() == 6) { // move past weekends , maybe skip this if date is available in data
1505
1501
  currentDate = new Date(currentDate.getTime() + 86400000);
1506
1502
  if (_this.settings.intradayDatePos.x == 'left' && (_this.settings.intradayDatePos.y == 'scale' || _this.settings.intradayDatePos.y == 'top')) {
1507
1503
  middleOfDay = new Date(currentDate.getTime());
@@ -1514,20 +1510,20 @@ function Milli_Chart(settings) {
1514
1510
  if (lastx != 0 && lastx + (getMaxTimeWidth() / 2) > (x - getMaxTimeWidth())) {
1515
1511
  draw = false;
1516
1512
  } else
1517
- if (m_zoom.mouseup.timestamp != null && firstDate.getTime() === currentDate.getTime())
1513
+ if (m_zoom.mouseup.timestamp != null && firstDate.getTime() === currentDate.getTime()) {
1518
1514
  draw = false;
1515
+ }
1519
1516
  if (draw) {
1520
1517
  lastx = x + 0.5;
1521
1518
  var text = formatChartTime(currentDate.toTimeString().substring(0, 8), _this.settings.timeformat);
1522
1519
  var date = formatDate(currentDate, _this.settings.intradayDatePos.dateformat, _this);
1523
- if (_this.scaleinfoX.lineLength + m_chartspaces.chart.left > x - getMaxTimeWidth()) {
1520
+ if (_this.scaleinfoX.lineLength + m_chartspaces.chart.left > x - getMaxTimeWidth()) { // not to far right?
1524
1521
  if (_this.settings.intradayDatePos.y == 'scale' && _this.settings.chartlen != '0d' && _this.settings.chartlen != '1d') {
1525
-
1522
+ // draw date on under time, todo fix setting name
1526
1523
  m_ctx.fillText(date, middleX - (m_ctx.measureText(date).width / 2), m_chartspaces.chart.bottom + getScaledSetting(m_xLegendCss.paddingTop));
1527
1524
  legendItems.push({ x: middleX, type: 0, text: date, width: m_ctx.measureText(date) });
1528
1525
  } else if (_this.settings.intradayDatePos.y == 'bottom' && _this.settings.chartlen != '0d' && _this.settings.chartlen != '1d') {
1529
1526
  m_ctx.fillText(date, middleX - (m_ctx.measureText(date).width / 2), m_chartspaces.chart.bottom + getScaledSetting(m_xLegendCss.paddingTop) + parseInt(m_xLegendCss.fontSize) * window.devicePixelRatio);
1530
-
1531
1527
  m_ctx.fillText(text, x - (m_ctx.measureText(text).width / 2), m_chartspaces.chart.bottom + getScaledSetting(m_xLegendCss.paddingTop));
1532
1528
  legendItems.push({ x: x, type: 0, text: text });
1533
1529
  } else {
@@ -1547,7 +1543,7 @@ function Milli_Chart(settings) {
1547
1543
  if (_this.settings.intradayDatePos.x == 'center') {
1548
1544
  m_ctx.fillText(date, middleX - (m_ctx.measureText(date).width / 2), getScaledSetting(m_chartCss.marginTop));
1549
1545
  } else {
1550
-
1546
+ //m_ctx.fillText(date, x - (m_ctx.measureText(date).width / 2), getScaledSetting(m_chartCss.marginTop));
1551
1547
  m_ctx.fillText(date, middleX + 1, getScaledSetting(m_chartCss.marginTop));
1552
1548
  }
1553
1549
  }
@@ -1555,17 +1551,17 @@ function Milli_Chart(settings) {
1555
1551
  }
1556
1552
  }
1557
1553
  }
1558
- if (x != m_chartspaces.chart.left + 0.5) {
1554
+ if (x != m_chartspaces.chart.left + 0.5) { // do not draw the first line, it is already drawn
1559
1555
  if (_this.settings.intradayDatePos.y != 'bottom') {
1560
1556
  if (openhour == currentDate.getTime() % 86400000) {
1561
- drawXAxisGridlines({ 'x': x, y: m_chartspaces.chart.bottom }, true);
1557
+ drawXAxisGridlines({ 'x': x, y: m_chartspaces.chart.bottom }, true); // dash?
1562
1558
  } else {
1563
- drawXAxisGridlines({ 'x': x, y: m_chartspaces.chart.bottom }, false);
1559
+ drawXAxisGridlines({ 'x': x, y: m_chartspaces.chart.bottom }, false); // dash?
1564
1560
  }
1565
1561
  }
1566
1562
  }
1567
1563
  }
1568
-
1564
+ // Move to next day and set starting hour correct if we have open at half hour
1569
1565
  currentDate = new Date(currentDate.getTime() + 86400000);
1570
1566
  currentDate = new Date(currentDate.toISOString().substring(0, 10) + 'T' + _this.instruments[0].marketopen + 'Z');
1571
1567
  middleOfDay = new Date(currentDate.getTime() - (currentDate.getTime() % 86400000) + ((openhour + closehour) / 2));
@@ -1573,23 +1569,23 @@ function Milli_Chart(settings) {
1573
1569
  middleOfDay = new Date(currentDate);
1574
1570
  }
1575
1571
 
1576
- if (currentDate.getTime() % 3600000 != 0)
1577
- currentDate = new Date(currentDate.getTime() - currentDate.getTime() % 3600000 + 3600000);
1578
-
1572
+ if (currentDate.getTime() % 3600000 != 0) // if not full hour, move up to next full hour
1573
+ currentDate = new Date(currentDate.getTime() - currentDate.getTime() % 3600000 + 3600000); // START om full hour (if modulo == 0 then + 3600000 kanske)
1574
+ //}
1579
1575
  offset += (86400000 - _this.scaleinfoX.milliPerDay) / _this.scaleinfoX.timePerPixel;
1580
1576
  }
1581
1577
  }
1582
-
1578
+ // add timestamps
1583
1579
  currentDate = new Date(starttime);
1584
- if (currentDate.getTime() % 3600000 != 0)
1585
- currentDate = new Date(currentDate.getTime() - currentDate.getTime() % 3600000 + 3600000);
1580
+ if (currentDate.getTime() % 3600000 != 0) // if not full hour, move up to next full hour
1581
+ currentDate = new Date(currentDate.getTime() - currentDate.getTime() % 3600000 + 3600000); // START om full hour (if modulo == 0 then + 3600000 kanske)
1586
1582
 
1587
1583
  var maxHourLegends;
1588
1584
  if (legendItems.length == 0)
1589
- maxHourLegends = Math.floor((_this.scaleinfoX.lineLength - m_chartspaces.chart.left - getMaxTimeWidth()) / (getMaxTimeWidth() * 3));
1585
+ maxHourLegends = Math.floor((_this.scaleinfoX.lineLength - m_chartspaces.chart.left - getMaxTimeWidth()) / (getMaxTimeWidth() * 3)); // varför tar vi bort margin???
1590
1586
  else if (legendItems.length == 1) {
1591
1587
  if (m_zoom.mouseup.timestamp && days == 2) {
1592
-
1588
+ // ta den största delen av linjen och mät på
1593
1589
  if (_this.scaleinfoX.lineLength / 2 < legendItems[0].x + m_chartspaces.chart.left)
1594
1590
  maxHourLegends = Math.floor((_this.scaleinfoX.lineLength - (_this.scaleinfoX.lineLength - legendItems[0].x) - getMaxTimeWidth()) / (getMaxTimeWidth() * 3));
1595
1591
  else
@@ -1597,15 +1593,15 @@ function Milli_Chart(settings) {
1597
1593
  } else
1598
1594
  maxHourLegends = Math.floor((_this.scaleinfoX.lineLength - legendItems[0].x - getMaxTimeWidth()) / (getMaxTimeWidth() * 3));
1599
1595
  } else {
1600
- maxHourLegends = Math.floor((legendItems[legendItems.length - 1].x - legendItems[legendItems.length - 2].x - getMaxTimeWidth()) / (getMaxTimeWidth() * 3));
1596
+ maxHourLegends = Math.floor((legendItems[legendItems.length - 1].x - legendItems[legendItems.length - 2].x - getMaxTimeWidth()) / (getMaxTimeWidth() * 3)); // calculate with the last days length
1601
1597
  }
1602
1598
 
1603
- var tickSize;
1599
+ var tickSize; // per day
1604
1600
  if (days == 1) {
1605
-
1601
+ // use start and endtime as ticksize
1606
1602
  tickSize = new Date(endtime - starttime);
1607
- } else if (m_zoom.mouseup.timestamp && days == 2) {
1608
-
1603
+ } else if (m_zoom.mouseup.timestamp && days == 2) { // zoom with 2 days
1604
+ // use the day with most time as tickSize
1609
1605
  var tmpDate = new Date(starttime);
1610
1606
  tickSize = new Date(new Date(tmpDate.toISOString().substring(0, 10) + 'T' + _this.instruments[0].marketclose + 'Z') - new Date(starttime)).getTime();
1611
1607
  var firstDay = tickSize;
@@ -1614,13 +1610,13 @@ function Milli_Chart(settings) {
1614
1610
  tickSize += new Date(endtime - new Date(tmpDate.toISOString().substring(0, 10) + 'T' + _this.instruments[0].marketopen + 'Z').getTime()).getTime();
1615
1611
  tickSize = new Date(Math.max(firstDay, secondDay));
1616
1612
  } else {
1617
-
1613
+ // use full day as tickSize
1618
1614
  tickSize = new Date(new Date(currentDate.toISOString().substring(0, 10) + 'T' + _this.instruments[0].marketclose + 'Z') - new Date(currentDate.toISOString().substring(0, 10) + 'T' + _this.instruments[0].marketopen + 'Z'));
1619
1615
  }
1620
1616
  var interval;
1621
1617
  var modularvalue = 3600000;
1622
1618
 
1623
-
1619
+ // calc the ticksize to add to time(interval) when drawing and the modulu value
1624
1620
  if (tickSize.getTime() < 1800000) {
1625
1621
  tickSize = tickSize.getTime() / 60000;
1626
1622
  interval = Math.floor(tickSize / (maxHourLegends + 1)) * 60000;
@@ -1639,14 +1635,14 @@ function Milli_Chart(settings) {
1639
1635
  interval = Math.floor(tickSize / (maxHourLegends + 1)) * 3600000;
1640
1636
  }
1641
1637
  if (interval == 0) {
1642
-
1638
+ // default 1h
1643
1639
  interval = 3600000;
1644
1640
  modularvalue = 3600000;
1645
1641
  }
1646
1642
  if (interval % 60000 != 0) {
1647
- interval = (interval - interval % 60000) + 60000;
1643
+ interval = (interval - interval % 60000) + 60000; // remove sekunder
1648
1644
  }
1649
-
1645
+ // print other times
1650
1646
  offset = 0;
1651
1647
  lastx = 0;
1652
1648
  var closeTime = new Date(currentDate.toISOString().substring(0, 10) + 'T' + _this.instruments[0].marketclose + 'Z');
@@ -1655,41 +1651,41 @@ function Milli_Chart(settings) {
1655
1651
 
1656
1652
  var workDate = new Date(currentDate);
1657
1653
  currentDate = new Date(starttime);
1658
- if (currentDate.getTime() % modularvalue != 0)
1659
- currentDate = new Date(currentDate.getTime() - currentDate.getTime() % modularvalue + modularvalue);
1654
+ if (currentDate.getTime() % modularvalue != 0) // if not full hour, move up to next full hour
1655
+ currentDate = new Date(currentDate.getTime() - currentDate.getTime() % modularvalue + modularvalue); // START om full hour (if modulo == 0 then + 3600000 kanske)
1660
1656
 
1661
1657
  var count = 0;
1662
1658
  while (currentDate.getTime() <= _this.scaleinfoX.endTimeStamp) {
1663
1659
  dayLightChange = (closeTime.getTimezoneOffset() - new Date().getTimezoneOffset()) * 60000;
1664
1660
  if (count++ > 100) {
1665
- break;
1661
+ break; // just make sure we dont do an infinity loop
1666
1662
 
1667
1663
  }
1668
1664
  draw = true;
1669
- while (currentDate.getDay() == 0 || currentDate.getDay() == 6) {
1670
-
1671
- currentDate = new Date(currentDate.getTime() + 86400000);
1672
- closeTime = new Date(currentDate.toISOString().substring(0, 10) + 'T' + _this.instruments[0].marketclose + 'Z');
1673
- if (currentDate.getTime() % modularvalue != 0)
1674
- currentDate = new Date(currentDate.getTime() - currentDate.getTime() % modularvalue + modularvalue);
1675
- workDate = new Date(workDate.getTime() + 86400000);
1676
- offset += 86400000 / _this.scaleinfoX.timePerPixel;
1677
- }
1665
+ // bytt plats if och while nedan 2022-11-07
1678
1666
  if (currentDate.getTime() > closeTime.getTime()) {
1679
-
1667
+ // draw DayEnd(start) dash line
1680
1668
  var dayStart = new Date(workDate.toISOString().substring(0, 10) + 'T' + _this.instruments[0].marketclose + 'Z');
1681
1669
  x = Math.round(m_chartspaces.chart.left + ((dayStart.getTime() - _this.scaleinfoX.startDate.getTime()) / _this.scaleinfoX.timePerPixel) - offset);
1682
- drawXAxisGridlines({ 'x': x, y: m_chartspaces.chart.bottom }, true);
1670
+ drawXAxisGridlines({ 'x': x, y: m_chartspaces.chart.bottom }, true); // dash?
1683
1671
 
1684
1672
  closeTime = new Date(closeTime.getTime() + 86400000);
1685
1673
  workDate = new Date(workDate.getTime() + 86400000);
1686
1674
  currentDate = new Date(workDate.toISOString().substring(0, 10) + 'T' + _this.instruments[0].marketopen + 'Z');
1687
1675
 
1688
- if (currentDate.getTime() % modularvalue != 0)
1689
- currentDate = new Date(currentDate.getTime() - currentDate.getTime() % modularvalue + modularvalue);
1676
+ if (currentDate.getTime() % modularvalue != 0) // if not full hour, move up to next full hour
1677
+ currentDate = new Date(currentDate.getTime() - currentDate.getTime() % modularvalue + modularvalue); // START om full hour (if modulo == 0 then + 3600000 kanske)
1690
1678
  offset += (86400000 - _this.scaleinfoX.milliPerDay) / _this.scaleinfoX.timePerPixel;
1691
1679
  continue;
1692
1680
  }
1681
+ while (currentDate.getDay() == 0 || currentDate.getDay() == 6) { // move past weekends , maybe skip this if date is available in data
1682
+ currentDate = new Date(currentDate.getTime() + 86400000);
1683
+ closeTime = new Date(currentDate.toISOString().substring(0, 10) + 'T' + _this.instruments[0].marketclose + 'Z');
1684
+ if (currentDate.getTime() % modularvalue != 0) // if not full hour, move up to next full hour
1685
+ currentDate = new Date(currentDate.getTime() - currentDate.getTime() % modularvalue + modularvalue); // START om full hour (if modulo == 0 then + 3600000 kanske)
1686
+ workDate = new Date(workDate.getTime() + 86400000);
1687
+ offset += 86400000 / _this.scaleinfoX.timePerPixel;
1688
+ }
1693
1689
  x = Math.round(m_chartspaces.chart.left + ((currentDate.getTime() - _this.scaleinfoX.startDate.getTime()) / _this.scaleinfoX.timePerPixel) - offset);
1694
1690
  for (var i = 0; i < legendItems.length; i++) {
1695
1691
  if (x < legendItems[i].x && x + (getMaxTimeWidth() / 2) > (legendItems[i].x - getMaxTimeWidth())) {
@@ -1706,23 +1702,23 @@ function Milli_Chart(settings) {
1706
1702
  }
1707
1703
  }
1708
1704
  if (lastx + (getMaxTimeWidth() / 2) > (x - getMaxTimeWidth())) {
1709
-
1705
+ //draw = false;
1710
1706
  }
1711
1707
  if (draw) {
1712
1708
  lastx = x;
1713
-
1714
- if (_this.scaleinfoX.lineLength + m_chartspaces.chart.left > x - getMaxTimeWidth()) {
1709
+ // if day change and setting print on top as well
1710
+ if (_this.scaleinfoX.lineLength + m_chartspaces.chart.left > x - getMaxTimeWidth()) { // not to far right?
1715
1711
  var label = formatChartTime(currentDate.toTimeString().substring(0, 8), _this.settings.timeformat);
1716
1712
  x = Math.round(x);
1717
1713
  m_ctx.fillText(label, x - (m_ctx.measureText(label).width / 2), m_chartspaces.chart.bottom + getScaledSetting(m_xLegendCss.paddingTop));
1718
- legendItems.push({ x: x, type: 0 });
1714
+ legendItems.push({ x: x, type: 0, text: label });
1719
1715
  }
1720
1716
  drawXAxisGridlines({ 'x': x, y: m_chartspaces.chart.bottom }, false);
1721
1717
  }
1722
1718
  currentDate = new Date(currentDate.getTime() + interval);
1723
1719
  }
1724
1720
 
1725
-
1721
+ // vad är detta?
1726
1722
  if (typeof m_chartCss.boxShadow !== 'undefined' && typeof m_chartCss.boxShadow.rightWidth !== 'undefined') {
1727
1723
  if (m_chartCss.boxShadow.rightWidth == 0) drawXAxisGridlines({ 'x': x, y: m_chartspaces.chart.bottom }, false);
1728
1724
 
@@ -1756,11 +1752,15 @@ function Milli_Chart(settings) {
1756
1752
  var oldValue = undefined;
1757
1753
  var newValue = undefined;
1758
1754
  var offsetWidth = 0;
1759
- if (_this.settings.drawyaxis && m_yLegendCss.float == 'right') {
1755
+ if (_this.instruments[0].pricetype == 'yield') {
1756
+ newValue = formatNiceNumber(obj.instruments[0].price, _this.settings.thousandseparator, _this.settings.decimalseparator, _this.settings.num_decimals, false);
1757
+ if (m_y2LegendCss.textAlign == 'left') offsetWidth = 1;
1758
+ } else if (_this.settings.drawyaxis && m_yLegendCss.float == 'right') {
1760
1759
  newValue = formatNiceNumber(obj.instruments[0].price, _this.settings.thousandseparator, _this.settings.decimalseparator, _this.settings.num_decimals, false);
1761
1760
  if (m_yLegendCss.textAlign == 'left') offsetWidth = 1;
1762
1761
  } else if (_this.settings.drawy2axis && m_y2LegendCss.float == 'right') {
1763
- newValue = formatNiceNumber(obj.instruments[0].diff, _this.settings.thousandseparator, _this.settings.decimalseparator, 2, false) + '%';
1762
+ if (obj.instruments[0].diff > 0) newValue = '+' + formatNiceNumber(obj.instruments[0].diff, _this.settings.thousandseparator, _this.settings.decimalseparator, 2, false) + '%';
1763
+ else newValue = formatNiceNumber(obj.instruments[0].diff, _this.settings.thousandseparator, _this.settings.decimalseparator, 2, false) + '%';
1764
1764
  if (m_y2LegendCss.textAlign == 'left') offsetWidth = 1;
1765
1765
  } else return;
1766
1766
  if (typeof m_priceIndicator !== 'undefined') {
@@ -1771,7 +1771,7 @@ function Milli_Chart(settings) {
1771
1771
  m_priceIndicator.setAttribute('class', 'millistream-chart-price-indicator');
1772
1772
  }
1773
1773
  m_priceIndicator.innerHTML = newValue;
1774
- m_priceIndicator.style.left = (m_chartspaces.chart.right / window.devicePixelRatio) - (offsetWidth == 0 ? -1 : m_priceIndicator.offsetWidth) + 'px';
1774
+ m_priceIndicator.style.left = (m_chartspaces.chart.right / window.devicePixelRatio) - (offsetWidth == 0 ? -1 : m_priceIndicator.offsetWidth) + 'px'; // offsetWidth with devicePixelRatio???
1775
1775
  m_priceIndicator.style.top = obj.instruments[0].y - (m_priceIndicator.offsetHeight / 2) + 'px';
1776
1776
  newValue = MillistreamWidgetApi_getElementNumber(_this, m_priceIndicator);
1777
1777
  MillistreamWidgetApi_flashElement(_this, m_priceIndicator, newValue, oldValue);
@@ -1850,6 +1850,8 @@ function Milli_Chart(settings) {
1850
1850
  var instr = {};
1851
1851
  instr.chartType = _this.scaleinfoY.type;
1852
1852
  instr.name = _this.instruments[x].name;
1853
+ instr.instrumenttype = _this.instruments[x].instrumenttype;
1854
+ instr.pricetype = _this.instruments[x].pricetype;
1853
1855
  if (typeof _this.instruments[x].symbol !== 'undefined')
1854
1856
  instr.symbol = _this.instruments[x].symbol;
1855
1857
 
@@ -1858,13 +1860,13 @@ function Milli_Chart(settings) {
1858
1860
  instr.data.price = formatNiceNumber(instr.data.price, _this.settings.thousandseparator, _this.settings.decimalseparator, _this.settings.num_decimals, false);
1859
1861
 
1860
1862
  if (typeof _this.instruments[x].toolTip === 'undefined') {
1861
-
1863
+ // add textdiv
1862
1864
  _this.instruments[x].toolTip = document.createElement('div');
1863
1865
  _this.instruments[x].toolTip.style.display = _this.settings.tooltip.display;
1864
- _this.instruments[x].toolTip.setAttribute('class', 'millistream-chart-tooltip');
1866
+ _this.instruments[x].toolTip.setAttribute('class', 'millistream-chart-tooltip'); // set class so we can measure it might change below depending on position
1865
1867
  _this.instruments[x].toolTip.position = 'absolute';
1866
1868
  m_canvas.parentNode.appendChild(_this.instruments[x].toolTip);
1867
-
1869
+ // add pointer div
1868
1870
  _this.instruments[x].toolTipPointer = document.createElement('div');
1869
1871
  m_canvas.parentNode.appendChild(_this.instruments[x].toolTipPointer);
1870
1872
  _this.instruments[x].toolTipPointer.setAttribute('class', 'millistream-chart-pointer');
@@ -1879,16 +1881,16 @@ function Milli_Chart(settings) {
1879
1881
  var pointerWidth = _this.instruments[x].toolTipPointer.offsetWidth + parseInt(pointerStyle.marginLeft) + parseInt(pointerStyle.marginRight);
1880
1882
  var pointerHeight = _this.instruments[x].toolTipPointer.offsetHeight + parseInt(pointerStyle.marginTop) + parseInt(pointerStyle.marginBottom);
1881
1883
  var posy = obj.instruments[x].y - (_this.instruments[x].toolTip.offsetHeight / 2);
1882
- if (m_dataPoints.arr[i] + (_this.instruments[x].toolTip.offsetWidth * 1.5) > m_canvas.width) {
1883
-
1884
+ if (m_dataPoints.arr[i] + (_this.instruments[x].toolTip.offsetWidth * 1.5) > m_canvas.width) { // || m_dataPoints.arr[i] + (_this.instruments[x].toolTip.offsetWidth * 1.5) > m_canvas.width) { // TODO +10 should be calculated better
1885
+ // draw the hover to the left
1884
1886
  _this.instruments[x].toolTip.style.left = (obj.instruments[x].x - _this.instruments[x].toolTip.offsetWidth - (pointerWidth / 2)) + 1 + 'px';
1885
1887
  } else {
1886
-
1888
+ // draw hover to the right
1887
1889
  _this.instruments[x].toolTip.style.left = (obj.instruments[x].x + (pointerWidth / 2)) + 'px';
1888
1890
  }
1889
1891
  _this.instruments[x].toolTip.style.top = posy + 'px';
1890
1892
  toolArray.push({ top: (obj.instruments[x].y - (pointerHeight / 2)), instrument: x });
1891
- _this.instruments[x].toolTipPointer.style.left = (obj.instruments[x].x - (pointerWidth / 2)) + 1 + 'px';
1893
+ _this.instruments[x].toolTipPointer.style.left = (obj.instruments[x].x - (pointerWidth / 2)) + 1 + 'px'; // hmm plus 1??
1892
1894
  _this.instruments[x].toolTipPointer.style.top = (obj.instruments[x].y - (pointerHeight / 2)) + 'px';
1893
1895
  if (posy > highy) highy = posy;
1894
1896
  if (posy < lowy) lowy = posy;
@@ -1932,13 +1934,12 @@ function Milli_Chart(settings) {
1932
1934
  enddate: new Date(_this.scaleinfoX.endTimeStamp).toISOString().substring(0, 10)
1933
1935
  };
1934
1936
 
1935
- }
1937
+ };
1936
1938
 
1937
1939
  _this.setDateInterval = function(startdate, enddate) {
1938
1940
  startdate = startdate.replaceAll('\/', '-');
1939
1941
  enddate = enddate.replaceAll('\/', '-');
1940
1942
  m_zoom.mousedown.timestamp = findFirstWeekDay(new Date(startdate + 'T00:00:00Z'));
1941
- () => {};
1942
1943
 
1943
1944
  m_zoom.mouseup.timestamp = new Date(enddate + 'T00:00:00Z');
1944
1945
 
@@ -1947,7 +1948,7 @@ function Milli_Chart(settings) {
1947
1948
  m_zoom.mouseup.timestamp = new Date(m_zoom.mouseup.timestamp + 'T00:00:00Z');
1948
1949
  }
1949
1950
  _this.settings.chartlen = 'max';
1950
- _this.scaleinfoY.type == 'history';
1951
+ _this.scaleinfoY.type = 'history';
1951
1952
  _this.drawChart();
1952
1953
  };
1953
1954
 
@@ -1982,7 +1983,7 @@ function Milli_Chart(settings) {
1982
1983
  }
1983
1984
  }
1984
1985
  }
1985
- if (_this.scaleinfoY.type == 'trades' && count > 0 && _this.instruments[0].closeprice1d) return true;
1986
+ if (_this.scaleinfoY.type == 'trades' && count > 0 && _this.instruments[0].closeprice1d) return true; // we can draw on closeprice 1d -> first trade
1986
1987
  var y = (m_chartspaces.chart.bottom - m_chartspaces.chart.top) / 2 + m_chartspaces.chart.top;
1987
1988
  var x = (m_chartspaces.chart.right - m_chartspaces.chart.left) / 2 + m_chartspaces.chart.left;
1988
1989
  m_ctx.save();
@@ -2014,7 +2015,7 @@ function Milli_Chart(settings) {
2014
2015
 
2015
2016
  _this.drawChart = function() {
2016
2017
  if (m_zoom.isZooming) {
2017
- return;
2018
+ return; // prevent redraw due to push updates when zooming
2018
2019
  }
2019
2020
 
2020
2021
  for (var i = 0; i < _this.settings.indicators.length; i++) {
@@ -2057,7 +2058,7 @@ function Milli_Chart(settings) {
2057
2058
  m_dataPoints.map = new Map();
2058
2059
  m_dataPoints.arr = [];
2059
2060
  if (_this.instruments.length < 0) {
2060
- () => {};
2061
+ console.log('no chartdata');
2061
2062
  return;
2062
2063
  }
2063
2064
  calcChartSpaces();
@@ -2066,51 +2067,51 @@ function Milli_Chart(settings) {
2066
2067
  var len = parseInt(_this.settings.chartlen.substring(0, _this.settings.chartlen.length - 1));
2067
2068
  m_ctx.clearRect(0, 0, m_canvas.width, m_canvas.height);
2068
2069
  m_ctx.lineWidth = 1 / window.devicePixelRatio;
2069
- m_ctx.textBaseline = 'top';
2070
- var i;
2070
+ m_ctx.textBaseline = 'top'; // important!
2071
+ var s;
2071
2072
  if (period == 'd' && _this.settings.chartlen != 'ytd') {
2072
2073
  if (m_zoom.mousedown.timestamp) {
2073
2074
  _this.scaleinfoX.endTimeStamp = m_zoom.mouseup.timestamp > m_zoom.mousedown.timestamp ? m_zoom.mouseup.timestamp : m_zoom.mousedown.timestamp;
2074
2075
  _this.scaleinfoX.startTimeStamp = m_zoom.mouseup.timestamp < m_zoom.mousedown.timestamp ? m_zoom.mouseup.timestamp : m_zoom.mousedown.timestamp;
2075
2076
  } else {
2076
- _this.scaleinfoX.startTimeStamp = getTickStartDate(len);
2077
-
2078
-
2077
+ _this.scaleinfoX.startTimeStamp = getTickStartDate(len); // calc not to start with weekends
2078
+ // back up x days from quotedate if needed
2079
+ // TODO if startTimeStamp < quotedate -len borde det vara
2079
2080
  var quoteDate = businessDaysSubtraction(_this.instruments[0].quotedate, len);
2080
- if (_this.scaleinfoX.startTimeStamp - _this.scaleinfoX.startTimeStamp % 86400000 > quoteDate) {
2081
+ if (_this.scaleinfoX.startTimeStamp - _this.scaleinfoX.startTimeStamp % 86400000 > quoteDate) { // if startdate > quotedate back startdate
2081
2082
  _this.scaleinfoX.startTimeStamp -= _this.scaleinfoX.startTimeStamp - _this.scaleinfoX.startTimeStamp % 86400000;
2082
2083
  _this.scaleinfoX.startTimeStamp += quoteDate;
2083
2084
  }
2084
- _this.scaleinfoX.endTimeStamp = new Date();
2085
+ _this.scaleinfoX.endTimeStamp = new Date(); // om helg TODO
2085
2086
  if (len > 1)
2086
2087
  _this.scaleinfoX.endTimeStamp = new Date(_this.scaleinfoX.endTimeStamp.toISOString().substring(0, 10) + 'T' + _this.instruments[0].marketclose + 'Z').getTime();
2087
2088
  else if (len == 1) {
2088
-
2089
+ // check if startdate is not today (due to exchange is closed f ex DJ)
2089
2090
  if (_this.scaleinfoX.startTimeStamp % 86400000 != new Date().getTime() % 86400) {
2090
2091
  _this.scaleinfoX.endTimeStamp = new Date(new Date(_this.scaleinfoX.startTimeStamp).toISOString().substring(0, 10) + 'T' + _this.instruments[0].marketclose + 'Z').getTime();
2091
2092
  } else
2092
2093
  _this.scaleinfoX.endTimeStamp = new Date(_this.scaleinfoX.endTimeStamp.toISOString().substring(0, 10) + 'T' + _this.instruments[0].marketclose + 'Z').getTime();
2093
2094
  } else {
2094
-
2095
+ // check that the last trade is not later than closetime
2095
2096
  var tradetimestamp = new Date(_this.instruments[0].trades[_this.instruments[0].trades.length - 1].timestamp).getTime();
2096
2097
  var closetimestamp = new Date(new Date(_this.instruments[0].trades[_this.instruments[0].trades.length - 1].timestamp).toISOString().substring(0, 10) + 'T' + _this.instruments[0].marketclose + 'Z').getTime();
2097
2098
  if (closetimestamp < tradetimestamp)
2098
- _this.scaleinfoX.endTimeStamp = new Date(closetimestamp);
2099
+ _this.scaleinfoX.endTimeStamp = new Date(closetimestamp); // borde inte rita med closeprice1d då heller eller spelar det ingen roll?
2099
2100
  else
2100
2101
  _this.scaleinfoX.endTimeStamp = new Date(tradetimestamp);
2101
2102
  }
2102
2103
  if (_this.scaleinfoX.endTimeStamp - (_this.scaleinfoX.endTimeStamp % 86400000) > _this.instruments[0].quotedate) {
2103
2104
  _this.scaleinfoX.endTimeStamp -= _this.scaleinfoX.endTimeStamp - _this.scaleinfoX.endTimeStamp % 86400000;
2104
- _this.scaleinfoX.endTimeStamp += _this.instruments[0].quotedate;
2105
+ _this.scaleinfoX.endTimeStamp += _this.instruments[0].quotedate; // set enddate = last Quotedate
2105
2106
  }
2106
2107
  }
2107
2108
  setTimeSpanData();
2108
2109
  _this.scaleinfoY.type = 'trades';
2109
2110
  if (_this.settings.absoluteScaling == true) {
2110
- for (var s = 1; s < _this.instruments.length; s++) _this.instruments[s].factor = 1;
2111
+ for (s = 1; s < _this.instruments.length; s++) _this.instruments[s].factor = 1;
2111
2112
  } else
2112
2113
  if (_this.instruments.length > 1) {
2113
-
2114
+ // calc factors
2114
2115
  var instrumentprice;
2115
2116
  for (i = 0; i < _this.instruments[0].trades.length; i++) {
2116
2117
  if (_this.instruments[0].trades[i].timestamp >= _this.scaleinfoX.startTimeStamp) {
@@ -2118,7 +2119,7 @@ function Milli_Chart(settings) {
2118
2119
  break;
2119
2120
  }
2120
2121
  }
2121
- for (var s = 1; s < _this.instruments.length; s++) {
2122
+ for (s = 1; s < _this.instruments.length; s++) {
2122
2123
  if (_this.instruments[s].insref != 0) {
2123
2124
  for (i = 0; i < _this.instruments[s].trades.length; i++) {
2124
2125
  if (_this.instruments[s].trades[i].timestamp >= _this.scaleinfoX.startTimeStamp) {
@@ -2147,7 +2148,6 @@ function Milli_Chart(settings) {
2147
2148
 
2148
2149
  } else
2149
2150
  if (period == 'm') {
2150
- () => {};
2151
2151
 
2152
2152
  if (m_zoom.mousedown.timestamp) {
2153
2153
  _this.scaleinfoX.startTimeStamp = m_zoom.mousedown.timestamp > m_zoom.mouseup.timestamp ? m_zoom.mouseup.timestamp : m_zoom.mousedown.timestamp;
@@ -2162,12 +2162,12 @@ function Milli_Chart(settings) {
2162
2162
  if (_this.instruments[0].history.length > 1 && _this.scaleinfoX.startTimeStamp < _this.instruments[0].history[0].timestamp) _this.scaleinfoX.startTimeStamp = _this.instruments[0].history[0].timestamp;
2163
2163
 
2164
2164
  _this.scaleinfoX.endTimeStamp = new Date().getTime();
2165
- _this.scaleinfoX.endTimeStamp = _this.scaleinfoX.endTimeStamp - (_this.scaleinfoX.endTimeStamp % 86400000);
2165
+ _this.scaleinfoX.endTimeStamp = _this.scaleinfoX.endTimeStamp - (_this.scaleinfoX.endTimeStamp % 86400000); // TODO: detta kan vi nog ta bort eller skall det vara med closetime?
2166
2166
  }
2167
2167
  setTimeSpanData();
2168
2168
  _this.scaleinfoY.type = 'history';
2169
2169
  if (_this.settings.absoluteScaling == true) {
2170
- for (var s = 1; s < _this.instruments.length; s++) _this.instruments[s].factor = 1;
2170
+ for (s = 1; s < _this.instruments.length; s++) _this.instruments[s].factor = 1;
2171
2171
  } else calcCompareFactors('history');
2172
2172
  _this.instruments[0].factor = 1;
2173
2173
 
@@ -2197,7 +2197,7 @@ function Milli_Chart(settings) {
2197
2197
  _this.scaleinfoX.startTimeStamp = _this.instruments[0].history[0].timestamp;
2198
2198
  } else
2199
2199
  if (_this.settings.chartlen == 'ytd') {
2200
- _this.scaleinfoX.startTimeStamp = new Date(new Date().getFullYear() + '-01-01').getTime();
2200
+ _this.scaleinfoX.startTimeStamp = new Date(new Date().getFullYear() + '-01-01').getTime(); // TODO, hur skall vi göra här om det inte finns data runt här?
2201
2201
  } else {
2202
2202
  _this.scaleinfoX.startTimeStamp = new Date().getTime() - (86400000 * 365 * (isNaN(len) ? 1 : len));
2203
2203
  }
@@ -2205,12 +2205,12 @@ function Milli_Chart(settings) {
2205
2205
  _this.scaleinfoX.startTimeStamp = findFirstWeekDay(_this.scaleinfoX.startTimeStamp).getTime();
2206
2206
 
2207
2207
  _this.scaleinfoX.endTimeStamp = new Date().getTime();
2208
- _this.scaleinfoX.endTimeStamp = _this.scaleinfoX.endTimeStamp - (_this.scaleinfoX.endTimeStamp % 86400000);
2208
+ _this.scaleinfoX.endTimeStamp = _this.scaleinfoX.endTimeStamp - (_this.scaleinfoX.endTimeStamp % 86400000); // TODO: detta kan vi nog ta bort eller skall det vara med closetime?
2209
2209
  }
2210
2210
  setTimeSpanData();
2211
2211
  _this.scaleinfoY.type = 'history';
2212
2212
  if (_this.settings.absoluteScaling == true) {
2213
- for (var s = 1; s < _this.instruments.length; s++) _this.instruments[s].factor = 1;
2213
+ for (s = 1; s < _this.instruments.length; s++) _this.instruments[s].factor = 1;
2214
2214
  } else calcCompareFactors('history');
2215
2215
 
2216
2216
  _this.instruments[0].factor = 1;
@@ -2227,10 +2227,10 @@ function Milli_Chart(settings) {
2227
2227
 
2228
2228
  }
2229
2229
 
2230
-
2231
-
2232
-
2233
-
2230
+ /*for (const [key, a] of m_analyzisMethod.entries()) {
2231
+ if (a.method == 'bb') plotBollingerBand(a, 'history');
2232
+ else plotMovingAverage(a, 'history');
2233
+ }*/
2234
2234
  }
2235
2235
  drawBoxShadow(m_chartspaces.chart);
2236
2236
 
@@ -2241,14 +2241,14 @@ function Milli_Chart(settings) {
2241
2241
  }
2242
2242
  if (typeof m_chartCss.backgroundColor !== 'undefined') {
2243
2243
  m_ctx.save();
2244
-
2244
+ //if (_this.settings.curveOnTop == false)
2245
2245
  m_ctx.globalCompositeOperation = 'destination-over';
2246
2246
  m_ctx.fillStyle = m_chartCss.backgroundColor;
2247
-
2247
+ //m_ctx.fillRect(0, 0, m_canvas.width, m_canvas.height);
2248
2248
  m_ctx.fillRect(0, 0, m_canvas.width, m_canvas.height);
2249
2249
  m_ctx.restore();
2250
2250
  }
2251
-
2251
+ //onMouseOut();
2252
2252
  };
2253
2253
 
2254
2254
  function drawBoxShadow(space) {
@@ -2279,6 +2279,8 @@ function Milli_Chart(settings) {
2279
2279
  if (instr == null) return;
2280
2280
 
2281
2281
  if (typeof data.name !== 'undefined') instr.name = data.name;
2282
+ if (typeof data.instrumenttype !== 'undefined') instr.instrumenttype = data.instrumenttype;
2283
+ else instr.instrumenttype = -1;
2282
2284
  if (typeof data.pricetype !== 'undefined') instr.pricetype = data.pricetype;
2283
2285
  else instr.pricetype = 'price';
2284
2286
  if (typeof data.symbol !== 'undefined') instr.symbol = data.symbol;
@@ -2286,7 +2288,7 @@ function Milli_Chart(settings) {
2286
2288
 
2287
2289
  if (typeof data.tradecurrency !== 'undefined') instr.tradecurrency = data.tradecurrency;
2288
2290
  if (data.marketopen && data.marketclose) {
2289
- if (new Date('2020-01-01T' + data.marketopen + 'Z') > new Date('2020-01-01T' + data.marketclose + 'Z')) {
2291
+ if (new Date('2020-01-01T' + data.marketopen + 'Z') > new Date('2020-01-01T' + data.marketclose + 'Z')) { // om close är tidiagre än open så sätter vi nedan tider
2290
2292
  data.marketopen = '00:00:00';
2291
2293
  data.marketclose = '22:00:00';
2292
2294
  }
@@ -2298,7 +2300,9 @@ function Milli_Chart(settings) {
2298
2300
  instr.quotedate = new Date().getTime();
2299
2301
  instr.quotedate -= instr.quotedate % 86400000;
2300
2302
  }
2301
-
2303
+ if (typeof data.time !== 'undefined') {
2304
+ instr.quotetime = ((parseInt(data.time) * 3600) + (parseInt(data.time.substring(3, 5)) * 60) + parseInt(data.time.substring(6, 8))) * 1000;
2305
+ } else instr.quotetime = 0;
2302
2306
  if (typeof data.marketopen !== 'undefined') {
2303
2307
  if (!data.marketopen) {
2304
2308
  data.marketopen = '00:00:00';
@@ -2318,7 +2322,7 @@ function Milli_Chart(settings) {
2318
2322
  instr.trades = [];
2319
2323
  instr.hashmap.clear();
2320
2324
  for (i = 0; i < data.trades.length; i++) {
2321
- if (data.trades[i].tradecode & 16) {
2325
+ if (data.trades[i].tradecode & 16) { // canceltrade
2322
2326
  continue;
2323
2327
  }
2324
2328
  item = [];
@@ -2335,7 +2339,7 @@ function Milli_Chart(settings) {
2335
2339
  }
2336
2340
  instr.trades.push(item);
2337
2341
  instr.hashmap.set(item.timestamp, item);
2338
-
2342
+ // we might have recieved trades from push before dataapi
2339
2343
  instr.trades.sort(function(a, b) {
2340
2344
  return a.timestamp - b.timestamp;
2341
2345
  });
@@ -2348,7 +2352,7 @@ function Milli_Chart(settings) {
2348
2352
  instr.history = [];
2349
2353
  for (i = 0; i < data.history.length; i++) {
2350
2354
  item = [];
2351
- if (typeof data.history[i].date !== 'undefined' && data.history[i].closeprice != null) {
2355
+ if (typeof data.history[i].date !== 'undefined' && data.history[i].closeprice != null) { // inget pris eller datum = onintressant, borde kanske skippas vid selecten i pitten också
2352
2356
  var timestamp = new Date(data.history[i].date + 'T00:00:00Z').getTime();
2353
2357
  item.timestamp = timestamp;
2354
2358
  } else continue;
@@ -2358,7 +2362,7 @@ function Milli_Chart(settings) {
2358
2362
  if (typeof data.history[i].dividend !== 'undefined') item.dividend = data.history[i].dividend;
2359
2363
  instr.history.push(item);
2360
2364
  }
2361
- if (_this.settings.hcurve && instr.history.length > 0) {
2365
+ if (_this.settings.hcurve && instr.history.length > 0) { // varför på all historik, och inte bara på hcurve
2362
2366
  if (!isToday(new Date(instr.history[instr.history.length - 1].timestamp))) {
2363
2367
  var addItem = {};
2364
2368
  MillistreamWidgetApi_AssignObject(instr.history[instr.history.length - 1], addItem);
@@ -2383,7 +2387,7 @@ function Milli_Chart(settings) {
2383
2387
  };
2384
2388
 
2385
2389
  function plotExternalHistoricalData(data) {
2386
-
2390
+ // används för dividend osv
2387
2391
  m_ctx.save();
2388
2392
  var startpoint = { x: 0, y: 0 };
2389
2393
  var endpoint = { x: 0, y: 0 };
@@ -2407,25 +2411,25 @@ function Milli_Chart(settings) {
2407
2411
  currentDate.setMinutes(lastdate.getMinutes());
2408
2412
  currentDate.setSeconds(lastdate.getSeconds());
2409
2413
 
2410
- if (lastdate.toISOString().substring(0, 10) != currentDate.toISOString().substring(0, 10)) {
2414
+ if (lastdate.toISOString().substring(0, 10) != currentDate.toISOString().substring(0, 10)) { // new date
2411
2415
  var tmp = new Date(lastdate.toISOString().substring(0, 10) + 'T' + _this.instruments[0].marketclose + 'Z');
2412
2416
  var nextDate = new Date(data[i].timestamp);
2413
- tmp = tmp.getTime() + 86400000 - _this.scaleinfoX.milliPerDay;
2417
+ tmp = tmp.getTime() + 86400000 - _this.scaleinfoX.milliPerDay; // increase to next days starttime
2414
2418
  currentDate = new Date(tmp);
2415
2419
  while (dateDiffInDays(currentDate, nextDate) > 0) {
2416
2420
  if (currentDate.getDay() == 0 || currentDate.getDay() == 6)
2417
2421
  offset += 86400000 / _this.scaleinfoX.timePerPixel;
2418
2422
  else
2419
- offset += ((86400000 - _this.scaleinfoX.milliPerDay) / _this.scaleinfoX.timePerPixel);
2423
+ offset += ((86400000 - _this.scaleinfoX.milliPerDay) / _this.scaleinfoX.timePerPixel); // * dateDiffInDays(lastdate, currentDate);
2420
2424
  currentDate = new Date(currentDate.getTime() + 86400000);
2421
2425
  }
2422
- offset += ((86400000 - _this.scaleinfoX.milliPerDay) / _this.scaleinfoX.timePerPixel);
2426
+ offset += ((86400000 - _this.scaleinfoX.milliPerDay) / _this.scaleinfoX.timePerPixel); // * dateDiffInDays(lastdate, currentDate);
2423
2427
  lastdate = currentDate;
2424
2428
  startpoint.x = Math.round(m_chartspaces.chart.left + ((data[i].timestamp - startDate) / _this.scaleinfoX.timePerPixel)) + 0.5 - offset;
2425
-
2429
+ // TODO: här blir det fel när det är från 00:00: 23:59 men göms av tmpx < startpoint.x
2426
2430
 
2427
2431
  }
2428
-
2432
+ //startpoint.y = Math.round(m_canvas.height - getScaledSetting(m_chartCss.marginBottom) - (((data[i].price * factor) - _this.scaleinfoY.minValue) * _this.scaleinfoY.valuePerPixel)) + 0.5;
2429
2433
  startpoint.y = Math.round(m_chartspaces.chart.height - getScaledSetting(m_chartCss.marginBottom) - (((data[i].price * factor) - _this.scaleinfoY.minValue) * _this.scaleinfoY.valuePerPixel)) + 0.5;
2430
2434
  maxy = maxy > startpoint.y ? maxy : startpoint.y;
2431
2435
 
@@ -2467,19 +2471,19 @@ function Milli_Chart(settings) {
2467
2471
  var endtimeToday = new Date(data[i].timestamp);
2468
2472
  if (endtimeToday.getDay() == 0 || endtimeToday.getDay() == 6) continue;
2469
2473
  if (_this.scaleinfoY.type != 'history') {
2470
- endtimeToday = new Date(endtimeToday.toISOString().substring(0, 10) + 'T' + _this.instruments[0].marketclose + 'Z');
2474
+ endtimeToday = new Date(endtimeToday.toISOString().substring(0, 10) + 'T' + _this.instruments[0].marketclose + 'Z'); // borde räcka att göra 1 gång när det blir nytt datum
2471
2475
  }
2472
2476
  if (data[i].timestamp > endtimeToday.getTime()) {
2473
- continue;
2477
+ continue; // dataticks efter stängning ritas inte
2474
2478
  }
2475
2479
  currentDate = new Date(data[i].timestamp);
2476
2480
  currentDate.setHours(lastdate.getHours());
2477
2481
  currentDate.setMinutes(lastdate.getMinutes());
2478
2482
  currentDate.setSeconds(lastdate.getSeconds());
2479
- if (lastdate.toISOString().substring(0, 10) != currentDate.toISOString().substring(0, 10)) {
2483
+ if (lastdate.toISOString().substring(0, 10) != currentDate.toISOString().substring(0, 10)) { // new date
2480
2484
  tmp = new Date(lastdate.toISOString().substring(0, 10) + 'T' + _this.instruments[0].marketclose + 'Z');
2481
2485
  var nextDate = new Date(data[i].timestamp);
2482
- tmp = tmp.getTime() + 86400000 - _this.scaleinfoX.milliPerDay;
2486
+ tmp = tmp.getTime() + 86400000 - _this.scaleinfoX.milliPerDay; // increase to next days starttime
2483
2487
 
2484
2488
  currentDate = new Date(tmp);
2485
2489
  while (dateDiffInDays(currentDate, nextDate) > 0) {
@@ -2489,11 +2493,11 @@ function Milli_Chart(settings) {
2489
2493
  offset += ((86400000 - _this.scaleinfoX.milliPerDay) / _this.scaleinfoX.timePerPixel);
2490
2494
  currentDate = new Date(currentDate.getTime() + 86400000);
2491
2495
  }
2492
- offset += ((86400000 - _this.scaleinfoX.milliPerDay) / _this.scaleinfoX.timePerPixel);
2496
+ offset += ((86400000 - _this.scaleinfoX.milliPerDay) / _this.scaleinfoX.timePerPixel); // * dateDiffInDays(lastdate, currentDate);
2493
2497
  lastdate = currentDate;
2494
2498
  startpoint.x = Math.round(m_chartspaces.chart.left + ((data[i].timestamp - startDate) / _this.scaleinfoX.timePerPixel)) + 0.5 - offset;
2495
2499
 
2496
-
2500
+ // TODO: här blir det fel när det är från 00:00: 23:59 men göms av tmpx < startpoint.x
2497
2501
  if (_this.scaleinfoY.type == 'trades' && tmpx < startpoint.x) {
2498
2502
  ret.push(startpoint.x, startpoint.y);
2499
2503
  }
@@ -2529,7 +2533,7 @@ function Milli_Chart(settings) {
2529
2533
  if (line.length == 0) return;
2530
2534
  m_ctx.save();
2531
2535
  m_ctx.beginPath();
2532
- m_ctx.closePath();
2536
+ m_ctx.closePath(); // clear path
2533
2537
  m_ctx.moveTo(line[0].x, line[0].y);
2534
2538
  for (var i = 1; i < line.length; i++) {
2535
2539
  m_ctx.lineTo(line[i].x, line[i].y);
@@ -2560,7 +2564,7 @@ function Milli_Chart(settings) {
2560
2564
  }
2561
2565
  var sma = calcAnalyzisLine(data, 2);
2562
2566
  m_ctx.beginPath();
2563
- m_ctx.closePath();
2567
+ m_ctx.closePath(); // clear path
2564
2568
  m_ctx.moveTo(sma[0].x, sma[0].y);
2565
2569
  for (i = 0; i < sma.length; i++) m_ctx.lineTo(sma[i].x, sma[i].y);
2566
2570
  m_ctx.stroke();
@@ -2568,10 +2572,39 @@ function Milli_Chart(settings) {
2568
2572
  return;
2569
2573
  }
2570
2574
 
2575
+ function plotLower(valuePerPixel, lineLength) {
2576
+ m_ctx.save();
2577
+ m_ctx.strokeStyle = m_instrumentCss[0].color;
2578
+ m_ctx.lineWidth = m_instrumentCss[0].width;
2579
+ var width = Math.round(m_chartspaces.lowerChart.width / (m_datapoints.length + 1) / 2);
2580
+ if (width < 2) width = 2;
2581
+ else if (width > 20) width = 20;
2582
+ m_ctx.lineWidth = width;
2583
+ for (var i = 0; i < m_datapoints.length; i++) {
2584
+ var x = (m_datapoints[i].x + 0.5) * window.devicePixelRatio;
2585
+ m_ctx.lineWidth = width;
2586
+ if (x - width <= m_chartspaces.lowerChart.left) {
2587
+ m_ctx.lineWidth = width / 2;
2588
+ x += m_ctx.lineWidth / 2;
2589
+ } else
2590
+ if (x + width >= m_chartspaces.lowerChart.right) {
2591
+ m_ctx.lineWidth = width / 2;
2592
+ x -= m_ctx.lineWidth / 2 + 1;
2593
+ }
2594
+ m_ctx.beginPath();
2595
+ m_ctx.moveTo(x, m_chartspaces.lowerChart.bottom - 0.5);
2596
+ var y = Math.round(m_chartspaces.lowerChart.bottom - (m_datapoints[i].quantity * valuePerPixel)) - 1;
2597
+ m_ctx.closePath();
2598
+ m_ctx.lineTo(x, y - 0.5);
2599
+ m_ctx.stroke();
2600
+ }
2601
+ m_ctx.restore();
2602
+ }
2603
+
2571
2604
  function plotData(data, instrument) {
2572
2605
  m_ctx.save();
2573
2606
  if (_this.settings.curveOnTop == false)
2574
- m_ctx.globalCompositeOperation = 'destination-over';
2607
+ m_ctx.globalCompositeOperation = 'destination-over'; // dont draw over labels inside the chart
2575
2608
  m_ctx.strokeStyle = m_instrumentCss[instrument].color;
2576
2609
  var factor = _this.instruments[instrument].factor;
2577
2610
  var startpoint = { x: 0, y: 0 };
@@ -2580,7 +2613,6 @@ function Milli_Chart(settings) {
2580
2613
  var len = data.length;
2581
2614
  m_ctx.lineWidth = m_instrumentCss[instrument].width / window.devicePixelRatio;
2582
2615
  m_ctx.beginPath();
2583
-
2584
2616
  var startx = 0;
2585
2617
  var starty = 0;
2586
2618
  var lastdate = new Date(_this.scaleinfoX.startTimeStamp);
@@ -2589,10 +2621,10 @@ function Milli_Chart(settings) {
2589
2621
  var maxy = 0;
2590
2622
  var hCurveLastPoint = null;
2591
2623
  var quantity = 0;
2592
-
2624
+ var nextDate;
2593
2625
  for (var i = 0; i < len; i++) {
2594
- var currentDate;
2595
-
2626
+ var currentDate = new Date(data[i].timestamp);
2627
+ // var lastItem = data[i];
2596
2628
  var tmpx = startpoint.x;
2597
2629
  var tmp;
2598
2630
  if (data[i].timestamp < _this.scaleinfoX.startTimeStamp) {
@@ -2600,42 +2632,48 @@ function Milli_Chart(settings) {
2600
2632
  continue;
2601
2633
  }
2602
2634
  if (data[i].timestamp > _this.scaleinfoX.endTimeStamp) {
2603
- break;
2635
+ break; // continue?
2604
2636
  }
2605
2637
  if (data[i].timestamp > new Date().getTime())
2606
2638
  break;
2607
2639
 
2608
2640
  if (_this.scaleinfoY.type != 'history' && (data[i].timestamp % 86400000 < _this.instruments[0].opentimestamp || data[i].timestamp % 86400000 > _this.instruments[0].closetimestamp)) {
2609
-
2641
+ // stämmer detta kan det bli överlapp vid sommartid/vintertid?
2610
2642
  continue;
2611
2643
  }
2612
2644
  var endtimeToday = new Date(data[i].timestamp);
2613
- if (endtimeToday.getDay() == 0 || endtimeToday.getDay() == 6) continue;
2645
+ if (endtimeToday.getDay() == 0 || endtimeToday.getDay() == 6) continue; // do not draw weekends TODO: if main instrument has weekenddata draw it, but need to fix that in all drawfunctions
2614
2646
  if (_this.scaleinfoY.type != 'history') {
2615
- endtimeToday = new Date(endtimeToday.toISOString().substring(0, 10) + 'T' + _this.instruments[0].marketclose + 'Z');
2647
+ endtimeToday = new Date(endtimeToday.toISOString().substring(0, 10) + 'T' + _this.instruments[0].marketclose + 'Z'); // borde räcka att göra 1 gång när det blir nytt datum
2616
2648
  }
2617
2649
  if (data[i].timestamp > endtimeToday.getTime()) {
2618
- continue;
2650
+ continue; // dataticks efter stängning ritas inte
2619
2651
  }
2620
2652
 
2621
2653
  if (_this.scaleinfoY.type == 'history') {
2622
-
2623
-
2654
+ //var point = { price: data[i].price, open: null, x: endpoint.x - 0.5, y: endpoint.y - 0.5, timestamp: data[i].timestamp };
2655
+ //m_datapoints.push(point);
2624
2656
  } else
2625
- if (_this.settings.previousDayClose && addedcloseprice1d == false && m_zoom.mouseup.timestamp == null) {
2626
- currentDate = new Date(data[i].timestamp);
2627
- offset = ((86400000 - _this.scaleinfoX.milliPerDay) / _this.scaleinfoX.timePerPixel) * dateDiffInDays(new Date(startDate), currentDate);
2628
- tmp = new Date(currentDate.toISOString().substring(0, 10) + 'T' + _this.instruments[0].marketopen + 'Z');
2629
- endpoint.x = Math.round(m_chartspaces.chart.left + ((tmp.getTime() - startDate) / _this.scaleinfoX.timePerPixel)) + 0.5 - offset;
2630
-
2631
-
2632
- endpoint.y = Math.round(m_chartspaces.chart.height - getScaledSetting(m_chartCss.marginBottom) - (((parseFloat(_this.instruments[instrument].startValue)) - _this.scaleinfoY.minValue) * _this.scaleinfoY.valuePerPixel)) + 0.5;
2633
-
2634
-
2635
-
2636
-
2637
-
2638
-
2657
+ if (_this.settings.previousDayClose && addedcloseprice1d == false && m_zoom.mouseup.timestamp == null) { // only draw closeprice1d on today charts
2658
+ currentDate = new Date(startDate);
2659
+ if (_this.settings.chartlen == '1d' || _this.settings.chartlen == '0d') { // plot the closeprice1d
2660
+ endpoint.y = Math.round(m_chartspaces.chart.height - getScaledSetting(m_chartCss.marginBottom) - (((parseFloat(_this.instruments[instrument].closeprice1d)) - _this.scaleinfoY.minValue) * _this.scaleinfoY.valuePerPixel)) + 0.5;
2661
+ endpoint.x = m_chartspaces.chart.left + 0.5 - offset;
2662
+ } else {
2663
+ if (!isToday(new Date(data[i].timestamp))) {
2664
+ nextDate = new Date(data[i].timestamp);
2665
+ while (dateDiffInDays(currentDate, nextDate) > 0) {
2666
+ if (currentDate.getDay() == 0 || currentDate.getDay() == 6)
2667
+ offset += 86400000 / _this.scaleinfoX.timePerPixel;
2668
+ else
2669
+ offset += ((86400000 - _this.scaleinfoX.milliPerDay) / _this.scaleinfoX.timePerPixel); // * dateDiffInDays(lastdate, currentDate);
2670
+ currentDate = new Date(currentDate.getTime() + 86400000);
2671
+ }
2672
+ tmp = new Date(currentDate.toISOString().substring(0, 10) + 'T' + _this.instruments[0].marketopen + 'Z');
2673
+ endpoint.y = Math.round(m_chartspaces.chart.height - getScaledSetting(m_chartCss.marginBottom) - (((parseFloat(_this.instruments[instrument].startValue)) - _this.scaleinfoY.minValue) * _this.scaleinfoY.valuePerPixel)) + 0.5;
2674
+ endpoint.x = Math.round(m_chartspaces.chart.left + ((tmp.getTime() - startDate) / _this.scaleinfoX.timePerPixel)) + 0.5 - offset;
2675
+ }
2676
+ }
2639
2677
  m_ctx.moveTo(endpoint.x, endpoint.y);
2640
2678
  lastdate = new Date(data[i].timestamp);
2641
2679
  addedcloseprice1d = true;
@@ -2646,25 +2684,24 @@ function Milli_Chart(settings) {
2646
2684
  currentDate.setHours(lastdate.getHours());
2647
2685
  currentDate.setMinutes(lastdate.getMinutes());
2648
2686
  currentDate.setSeconds(lastdate.getSeconds());
2649
- if (lastdate.toISOString().substring(0, 10) != currentDate.toISOString().substring(0, 10)) {
2687
+ if (lastdate.toISOString().substring(0, 10) != currentDate.toISOString().substring(0, 10)) { // new date
2650
2688
  tmp = new Date(lastdate.toISOString().substring(0, 10) + 'T' + _this.instruments[0].marketclose + 'Z');
2651
-
2652
- var nextDate = new Date(data[i].timestamp);
2653
- tmp = tmp.getTime() + 86400000 - _this.scaleinfoX.milliPerDay;
2689
+ nextDate = new Date(data[i].timestamp);
2690
+ tmp = tmp.getTime() + 86400000 - _this.scaleinfoX.milliPerDay; // increase to next days starttime
2654
2691
 
2655
2692
  currentDate = new Date(tmp);
2656
2693
  while (dateDiffInDays(currentDate, nextDate) > 0) {
2657
2694
  if (currentDate.getDay() == 0 || currentDate.getDay() == 6)
2658
2695
  offset += 86400000 / _this.scaleinfoX.timePerPixel;
2659
2696
  else
2660
- offset += ((86400000 - _this.scaleinfoX.milliPerDay) / _this.scaleinfoX.timePerPixel);
2697
+ offset += ((86400000 - _this.scaleinfoX.milliPerDay) / _this.scaleinfoX.timePerPixel); // * dateDiffInDays(lastdate, currentDate);
2661
2698
  currentDate = new Date(currentDate.getTime() + 86400000);
2662
2699
  }
2663
- offset += ((86400000 - _this.scaleinfoX.milliPerDay) / _this.scaleinfoX.timePerPixel);
2700
+ offset += ((86400000 - _this.scaleinfoX.milliPerDay) / _this.scaleinfoX.timePerPixel); // * dateDiffInDays(lastdate, currentDate);
2664
2701
  lastdate = currentDate;
2665
2702
  startpoint.x = Math.round(m_chartspaces.chart.left + ((data[i].timestamp - startDate) / _this.scaleinfoX.timePerPixel)) + 0.5 - offset;
2666
2703
 
2667
-
2704
+ // TODO: här blir det fel när det är från 00:00: 23:59 men göms av tmpx < startpoint.x
2668
2705
  if (_this.scaleinfoY.type == 'trades' && tmpx < startpoint.x) {
2669
2706
  m_ctx.lineTo(startpoint.x, startpoint.y);
2670
2707
  }
@@ -2673,6 +2710,7 @@ function Milli_Chart(settings) {
2673
2710
  maxy = maxy > startpoint.y ? maxy : startpoint.y;
2674
2711
 
2675
2712
  startpoint.x = Math.round(m_chartspaces.chart.left + ((data[i].timestamp - _this.scaleinfoX.startDate.getTime()) / _this.scaleinfoX.timePerPixel)) + 0.5;
2713
+
2676
2714
  startpoint.x -= offset;
2677
2715
  quantity += data[i].quantity;
2678
2716
  if (startpoint.x != endpoint.x || startpoint.y != endpoint.y) {
@@ -2693,7 +2731,7 @@ function Milli_Chart(settings) {
2693
2731
  if (tmpx < startpoint.x) {
2694
2732
  if (_this.settings.hcurve) m_ctx.lineTo(startpoint.x, endpoint.y);
2695
2733
  m_ctx.lineTo(startpoint.x, startpoint.y);
2696
-
2734
+ //m_ctx.bezierCurveTo(startpoint.x, startpoint.y, endpoint.x - 1, endpoint.y - 1, endpoint.x, endpoint.y); // läs på om detta för "runda linjer"
2697
2735
 
2698
2736
  if (instrument == 0) {
2699
2737
  point = { price: data[i].price, open: data[i].openprice, x: startpoint.x / window.devicePixelRatio - 0.5, y: startpoint.y / window.devicePixelRatio - 0.5, timestamp: data[i].timestamp, date: new Date(data[i].timestamp), quantity: quantity };
@@ -2710,7 +2748,7 @@ function Milli_Chart(settings) {
2710
2748
  m_datapoints.push(point);
2711
2749
  if (_this.settings.hcurve && _this.scaleinfoY.type == 'history') {
2712
2750
  if (isToday(currentDate)) {
2713
-
2751
+ // only 1 point in hcurve chart, draw line from start of chart to end date
2714
2752
  m_ctx.moveTo(m_chartspaces.chart.left, startpoint.y);
2715
2753
  point = { price: data[i].price, open: data[i].openprice, x: m_chartspaces.chart.left / window.devicePixelRatio - 0.5, y: startpoint.y / window.devicePixelRatio - 0.5, timestamp: data[i].timestamp, date: new Date(data[i].timestamp), insref: _this.instruments[instrument].insref, diff: data[i].diff, quantity: quantity };
2716
2754
  m_datapoints.push(point);
@@ -2718,12 +2756,12 @@ function Milli_Chart(settings) {
2718
2756
  m_datapoints.push(point);
2719
2757
  startx = m_chartspaces.chart.left;
2720
2758
  starty = startpoint.y;
2721
-
2759
+ // last point so break out and store startx and starty from fake point
2722
2760
  break;
2723
2761
  } else if (hCurveLastPoint) {
2724
-
2725
-
2726
-
2762
+ /* var y = Math.round(m_canvas.height - getScaledSetting(m_chartCss.marginBottom) - (((hCurveLastPoint.price * factor) - _this.scaleinfoY.minValue) * _this.scaleinfoY.valuePerPixel)) + 0.5;
2763
+ m_ctx.moveTo(m_chartspaces.chart.left, y);
2764
+ m_ctx.lineTo(startpoint.x, y);*/
2727
2765
  }
2728
2766
  }
2729
2767
  quantity = 0;
@@ -2736,7 +2774,7 @@ function Milli_Chart(settings) {
2736
2774
  endpoint.y = startpoint.y;
2737
2775
  }
2738
2776
  if (data[i].dividend) {
2739
-
2777
+ //console.log('div', data[i]);
2740
2778
  }
2741
2779
  }
2742
2780
  m_dataPoints.arr.sort(function(a, b) {
@@ -2760,7 +2798,7 @@ function Milli_Chart(settings) {
2760
2798
  m_ctx.fill();
2761
2799
  } else
2762
2800
  m_ctx.closePath();
2763
-
2801
+ // eftersom vi kör med m_datapoints här så missar vi dom som plottas på samma ställe som punkten innan, gör vi det???
2764
2802
  if (instrument == 0) {
2765
2803
  drawPriceIndicator();
2766
2804
  drawClosePriceIndicator();
@@ -2769,13 +2807,13 @@ function Milli_Chart(settings) {
2769
2807
  m_ctx.restore();
2770
2808
  }
2771
2809
 
2772
-
2773
-
2774
-
2775
-
2776
-
2777
-
2778
-
2810
+ /* function drawCompare(resp) {
2811
+ parseData(resp[0], 1);
2812
+ _this.drawChart();
2813
+ requestStreaming();
2814
+ return;
2815
+ }
2816
+ */
2779
2817
 
2780
2818
  _this.setChartLength = function(len) {
2781
2819
  _this.settings.chartlen = len;
@@ -2907,7 +2945,7 @@ function Milli_Chart(settings) {
2907
2945
  };
2908
2946
  req.open("GET", url, true);
2909
2947
  req.onerror = function(error) {
2910
- () => {};
2948
+ console.log('Fetch data error', error);
2911
2949
  };
2912
2950
  req.send();
2913
2951
  }
@@ -2915,13 +2953,13 @@ function Milli_Chart(settings) {
2915
2953
  _this.refreshData = function() {
2916
2954
  _this.instruments.forEach(function(c, pos) {
2917
2955
  if (c.insref != 0) {
2918
- fetchTrades(c.insref);
2956
+ if (_this.settings.intradaylen) fetchTrades(c.insref);
2919
2957
  fetchHistory(c.insref);
2920
2958
  }
2921
2959
  });
2922
-
2960
+ //fetch data and redraw ( for no push charts)
2923
2961
  };
2924
-
2962
+ // Compare functions
2925
2963
  _this.removeAllCompares = function() {
2926
2964
  if (_this.instruments.length == 1) return;
2927
2965
  for (var i = 0; i < 3; i++)
@@ -2968,21 +3006,24 @@ function Milli_Chart(settings) {
2968
3006
 
2969
3007
  _this.instruments[pos] = instr;
2970
3008
 
2971
- fetchTrades(insref);
3009
+ if (_this.settings.intradaylen) fetchTrades(insref);
2972
3010
  fetchHistory(insref);
2973
3011
  return 1;
2974
3012
  };
2975
-
3013
+ // Size functions
2976
3014
 
2977
3015
  function setChartSize() {
2978
3016
  var offset = 0;
3017
+ // set canvas size to 0 so it does not prevent the div to resize
3018
+ _this.settings.target.style.height = '0px';
3019
+ _this.settings.target.style.width = '0px';
2979
3020
  if (_this.settings.target.parentNode.classList.contains('chartcontainer')) {
2980
3021
  offset = _this.settings.target.getBoundingClientRect().top - _this.settings.target.parentNode.getBoundingClientRect().top;
2981
3022
  }
2982
3023
  _this.settings.target.style.height = (_this.settings.target.parentNode.offsetHeight - offset) + 'px';
2983
3024
  _this.settings.target.style.width = _this.settings.target.parentNode.offsetWidth + 'px';
2984
-
2985
-
3025
+ //_this.settings.target.style.height = (_this.settings.target.parentNode.offsetHeight - offset) * window.devicePixelRatio + 'px';
3026
+ //_this.settings.target.style.width = _this.settings.target.parentNode.offsetWidth * window.devicePixelRatio + 'px';
2986
3027
  m_canvas.setRect(_this.settings.target.offsetHeight, _this.settings.target.offsetWidth);
2987
3028
  }
2988
3029
 
@@ -2991,7 +3032,7 @@ function Milli_Chart(settings) {
2991
3032
  m_resizing.height = m_canvas.height;
2992
3033
  };
2993
3034
 
2994
- _this.resize = function(e, ui) {
3035
+ _this.resizing = function(e, ui) {
2995
3036
  var diff = (m_resizing.height - m_canvas.height) / m_canvas.height * 100;
2996
3037
  if (Math.abs(diff) > 1) {
2997
3038
  setChartSize();
@@ -3002,8 +3043,8 @@ function Milli_Chart(settings) {
3002
3043
  diff = (m_resizing.width - m_canvas.width) / m_canvas.width * 100;
3003
3044
  if (Math.abs(diff) > 1) {
3004
3045
  setChartSize();
3005
-
3006
-
3046
+ //m_canvas.height = Math.floor(_this.settings.target.offsetHeight * window.devicePixelRatio);
3047
+ //m_canvas.width = Math.floor(_this.settings.target.offsetWidth * window.devicePixelRatio);
3007
3048
  m_resizing.width = m_canvas.width;
3008
3049
  m_resizing.height = m_canvas.height;
3009
3050
  _this.drawChart();
@@ -3035,11 +3076,11 @@ function Milli_Chart(settings) {
3035
3076
  m_canvas = MillistreamWidgetApi_addElement(_this, 'canvas', 'millistream-chart-canvas', _this.settings.target);
3036
3077
  m_ctx = m_canvas.getContext("2d");
3037
3078
  setChartSize();
3038
- m_canvas.addEventListener('mousemove', onMouseMove, false);
3079
+ m_canvas.addEventListener('mousemove', onMouseMove, false); // disable while loading and enable on drawReady
3039
3080
  m_canvas.addEventListener('mouseout', onMouseOut, false);
3040
3081
  m_canvas.style.cursor = "crosshair";
3041
3082
  m_canvas.onmousedown = (function(evt) {
3042
- if (!evt.which == 1) return;
3083
+ if (evt.which != 1) return; // ignore right and middle
3043
3084
  if (_this.settings.enablezoom == false) return;
3044
3085
  if (m_datapoints.length == 0) return;
3045
3086
  var rect = m_canvas.getBoundingClientRect();
@@ -3065,7 +3106,7 @@ function Milli_Chart(settings) {
3065
3106
  clearZoom();
3066
3107
  return;
3067
3108
  }
3068
- if (Math.abs(x - m_zoom.mousedown.pos) > 5) {
3109
+ if (Math.abs(x - m_zoom.mousedown.pos) > 5) { // only handle zoom with 5 pixels width
3069
3110
  var i;
3070
3111
  for (i = m_datapoints.length - 1; i > 0; i--) {
3071
3112
  if (x >= m_datapoints[i].x) {
@@ -3082,7 +3123,7 @@ function Milli_Chart(settings) {
3082
3123
  m_zoom.mousedown.pos = 0;
3083
3124
  m_zoom.mousedown.i = 0;
3084
3125
  if (m_zoom.mousedown.oldtimestamp != null) {
3085
- m_zoom.mousedown.timestamp = m_zoom.mousedown.oldtimestamp;
3126
+ m_zoom.mousedown.timestamp = m_zoom.mousedown.oldtimestamp; // so we do not unzoom if zoomed
3086
3127
  m_zoom.mousedown.oldtimestamp = null;
3087
3128
  } else
3088
3129
  m_zoom.mousedown.timestamp = null;
@@ -3129,12 +3170,15 @@ function Milli_Chart(settings) {
3129
3170
  if (instr.pricetype == 'price' || instr.pricetype == 'nav') {
3130
3171
  if (typeof json['148'] !== 'undefined') {
3131
3172
  instr.closeprice1d = parseFloat(json['148']);
3173
+ update = true;
3132
3174
  }
3133
3175
  } else
3134
3176
  if (typeof json['262'] !== 'undefined') {
3135
- instr.closeprice1d = parseFloat(json['148']);
3177
+ instr.closeprice1d = parseFloat(json['262']);
3178
+ update = true;
3136
3179
  }
3137
3180
  }
3181
+ var timestamp;
3138
3182
  if (mref == 'quote') {
3139
3183
  if (instr.history.length == 0) return;
3140
3184
  if (json['3'] && !isToday(new Date(json['3']))) return;
@@ -3143,9 +3187,12 @@ function Milli_Chart(settings) {
3143
3187
  instr.quotedate = new Date(json['3']).getTime();
3144
3188
  instr.quotedate -= instr.quotedate % 86400000;
3145
3189
  }
3190
+ if (json['4']) {
3191
+ instr.quotetime = ((parseInt(json[4]) * 3600) + (parseInt(json[4].substring(3, 5)) * 60) + parseInt(json[4].substring(6, 8))) * 1000;
3192
+ }
3146
3193
  var price = undefined;
3147
3194
  var quantity = undefined;
3148
- var timestamp = new Date().getTime();
3195
+ timestamp = new Date().getTime();
3149
3196
  timestamp -= timestamp % 86400000;
3150
3197
  var obj = instr.history[instr.history.length - 1];
3151
3198
  if (instr.pricetype == 'yield') {
@@ -3172,31 +3219,31 @@ function Milli_Chart(settings) {
3172
3219
  if (_this.scaleinfoY.type == 'history') update = true;
3173
3220
  } else {
3174
3221
  if (json['3'] && json['36'] && (json['12'] || json['201'])) {
3175
- var timestamp = new Date(json['3'] + 'T' + json['36'].substring(0, 6) + '00' + 'Z').getTime();
3222
+ timestamp = new Date(json['3'] + 'T' + json['36'].substring(0, 6) + '00' + 'Z').getTime();
3176
3223
  var data = instr.hashmap.get(timestamp);
3177
3224
  if (typeof data === 'undefined') {
3178
3225
  data = {};
3179
-
3226
+ //data.tradereference = json['14'];
3180
3227
  data.timestamp = timestamp;
3181
3228
  calcAnalyizis = true;
3182
3229
  if (instr.pricetype == 'price') {
3183
3230
  update = true;
3184
- data.price = parseFloat(json['12']);
3185
- data.open = parseFloat(json['12']);
3186
- data.high = parseFloat(json['12']);
3187
- data.low = parseFloat(json['12']);
3231
+ data.price = parseFloat(json['12']); // eller 201 för tradeyield
3232
+ data.open = parseFloat(json['12']); // eller 201 för tradeyield
3233
+ data.high = parseFloat(json['12']); // eller 201 för tradeyield
3234
+ data.low = parseFloat(json['12']); // eller 201 för tradeyield
3188
3235
  data.quantity = typeof json['13'] === 'undefined' ? 0 : parseInt(json['13']);
3189
- } else if (instr.pricetype == 'price') {
3190
- data.price = parseFloat(json['201']);
3191
- data.open = parseFloat(json['201']);
3192
- data.high = parseFloat(json['201']);
3193
- data.low = parseFloat(json['201']);
3236
+ } else if (instr.pricetype == 'yield') {
3237
+ data.price = parseFloat(json['201']); // eller 201 för tradeyield
3238
+ data.open = parseFloat(json['201']); // eller 201 för tradeyield
3239
+ data.high = parseFloat(json['201']); // eller 201 för tradeyield
3240
+ data.low = parseFloat(json['201']); // eller 201 för tradeyield
3194
3241
  data.quantity = typeof json['13'] === 'undefined' ? 0 : parseInt(json['13']);
3195
3242
  update = true;
3196
3243
  }
3197
3244
  if (update) {
3198
3245
  if (instr.trades.length != 0 && data.timestamp < instr.trades[instr.trades.length - 1].timestamp) {
3199
-
3246
+ // TODO console.log("pushtrade is older than last trade ignoring, should file it on correct postition");
3200
3247
  } else
3201
3248
  instr.hashmap.set(data.timestamp, data);
3202
3249
  instr.trades.push(data);
@@ -3205,24 +3252,24 @@ function Milli_Chart(settings) {
3205
3252
  if (instr.pricetype == 'price') {
3206
3253
  if (data.price != parseFloat(json['12']))
3207
3254
  calcAnalyizis = true;
3208
- data.price = parseFloat(json['12']);
3255
+ data.price = parseFloat(json['12']); // eller 201 för tradeyield
3209
3256
  data.quantity += typeof json['13'] === 'undefined' ? 0 : parseInt(json['13']);
3210
3257
  if (_this.scaleinfoY.type == 'trades') update = true;
3211
3258
  } else {
3212
- if (instr.pricetype == 'price') {
3259
+ if (instr.pricetype == 'yield') {
3213
3260
  if (data.price != parseFloat(json['201']))
3214
3261
  calcAnalyizis = true;
3215
- data.price = parseFloat(json['201']);
3262
+ data.price = parseFloat(json['201']); // eller 201 för tradeyield
3216
3263
  data.quantity += typeof json['13'] === 'undefined' ? 0 : parseInt(json['13']);
3217
3264
  if (_this.scaleinfoY.type == 'trades') update = true;
3218
3265
  }
3219
-
3266
+ // TODo: updatera med quantity, open , high,low osv?
3220
3267
  }
3221
3268
  }
3222
3269
  }
3223
3270
  if (calcAnalyizis && insref == _this.instruments[0].insref) {
3224
3271
  for (var i = 0; i < _this.settings.indicators.length; i++) {
3225
-
3272
+ //for (const [key, a] of m_analyzisMethod.entries()) {
3226
3273
  switch (_this.settings.indicators[i].method) {
3227
3274
  case 'sma':
3228
3275
  _this.settings.indicators[i].trades = [];
@@ -3237,7 +3284,7 @@ function Milli_Chart(settings) {
3237
3284
  _this.settings.indicators[i].trades = bollingerBands(_this.instruments[0].trades, _this.settings.indicators[i].method_length, _this.settings.indicators[i].stddev | 2);
3238
3285
  break;
3239
3286
  default:
3240
-
3287
+ // draw custom added?
3241
3288
  break;
3242
3289
  }
3243
3290
  }
@@ -3246,18 +3293,19 @@ function Milli_Chart(settings) {
3246
3293
  _this.drawChart();
3247
3294
  }
3248
3295
  return;
3249
- };
3250
- }
3296
+ }
3297
+ };
3251
3298
 
3252
-
3299
+ // used by trader
3253
3300
  _this.exportData = function() {
3254
3301
  let ret = [];
3255
-
3302
+ var i;
3303
+ var date, datestr;
3256
3304
  if (_this.scaleinfoY.type == 'trades') {
3257
3305
  if (_this.instruments.length > 0) {
3258
- for (var i = 0; i < _this.instruments[0].trades.length; i++) {
3259
- var date = new Date(_this.instruments[0].trades[i].timestamp - new Date().getTimezoneOffset() * 60000);
3260
- var datestr = date.toISOString();
3306
+ for (i = 0; i < _this.instruments[0].trades.length; i++) {
3307
+ date = new Date(_this.instruments[0].trades[i].timestamp - new Date().getTimezoneOffset() * 60000); // tz_offset in minutes
3308
+ datestr = date.toISOString();
3261
3309
 
3262
3310
  ret.push([datestr.substring(0, 10), datestr.substring(11, 23), _this.instruments[0].trades[i].price, _this.instruments[0].trades[i].quantity]);
3263
3311
  }
@@ -3269,9 +3317,9 @@ function Milli_Chart(settings) {
3269
3317
  ];
3270
3318
  } else {
3271
3319
  if (_this.instruments.length > 0) {
3272
- for (var i = 0; i < _this.instruments[0].history.length; i++) {
3273
- var date = new Date(_this.instruments[0].history[i].timestamp);
3274
- var datestr = date.toISOString();
3320
+ for (i = 0; i < _this.instruments[0].history.length; i++) {
3321
+ date = new Date(_this.instruments[0].history[i].timestamp);
3322
+ datestr = date.toISOString();
3275
3323
 
3276
3324
  ret.push([datestr.substring(0, 10), "", _this.instruments[0].history[i].price, _this.instruments[0].history[i].quantity]);
3277
3325
  }
@@ -3282,10 +3330,10 @@ function Milli_Chart(settings) {
3282
3330
  ...ret
3283
3331
  ];
3284
3332
  }
3285
- }
3333
+ };
3286
3334
 
3287
3335
  _this.destroyWidget = function() {
3288
-
3336
+ // if we have subscriptions send in an empty array to unsubscribe all and release it
3289
3337
  if (MillistreamWidgetApi_isObjectEmpty(_this.unsubscriptions) == false)
3290
3338
  _this.requestid = _this.settings.streaming.MillistreamWidgetStreamingApi_subscribeInstruments(_this, _this.requestid, []);
3291
3339
  return 0;
@@ -3309,23 +3357,25 @@ function Milli_Chart(settings) {
3309
3357
  }
3310
3358
 
3311
3359
  function fetchHistory(instrument) {
3312
- var oldfields = _this.settings.fields;
3313
- _this.settings.fields = [...['name', 'tradecurrency', 'date', 'closeprice', 'closequantity', 'marketopen', 'marketclose'], ...oldfields];
3314
- var url = milli_data_api_url + "widget=historychart&token=" + _this.settings.token + "&target=buildwidget&fields=" + _this.settings.fields + "&language=sv&insref=" + instrument + '&startdate=' + m_startdate + '&intradaylen=' + _this.settings.intradaylen + '&xhr=' + (_this.settings.xhr == true ? '1' : '0');
3315
- if (typeof _this.settings.pricetype !== 'undefined') url += '&pricingtype=' + _this.settings.pricetype;
3316
- if (_this.settings.adjusted == true) url += '&adjusted=1';
3317
- _this.settings.fields = oldfields;
3318
- if (_this.settings.xhr) {
3319
- getXhrJson(url);
3320
- } else {
3321
- millistream_data_api.fetch(url, function(data) {
3322
- _this.buildwidget(data);
3323
- });
3360
+ if (_this.settings.historylen) {
3361
+ var oldfields = _this.settings.fields;
3362
+ _this.settings.fields = [...['name', 'tradecurrency', 'date', 'closeprice', 'closequantity', 'marketopen', 'marketclose'], ...oldfields];
3363
+ var url = milli_data_api_url + "widget=historychart&token=" + _this.settings.token + "&target=buildwidget&fields=" + _this.settings.fields + "&language=sv&insref=" + instrument + '&startdate=' + m_startdate + '&intradaylen=' + _this.settings.intradaylen + '&xhr=' + (_this.settings.xhr == true ? '1' : '0');
3364
+ if (typeof _this.settings.pricetype !== 'undefined') url += '&pricingtype=' + _this.settings.pricetype;
3365
+ if (_this.settings.adjusted == true) url += '&adjusted=1';
3366
+ _this.settings.fields = oldfields;
3367
+ if (_this.settings.xhr) {
3368
+ getXhrJson(url);
3369
+ } else {
3370
+ millistream_data_api.fetch(url, function(data) {
3371
+ _this.buildwidget(data);
3372
+ });
3373
+ }
3324
3374
  }
3325
3375
  }
3326
3376
 
3327
3377
  _this.drawWidget = function() {
3328
-
3378
+ // remove standard fields from array, they will be requested anyway
3329
3379
  _this.settings.fields = _this.settings.fields.filter(function(obj) {
3330
3380
  return ['name', 'tradecurrency', 'time', 'date', 'tradeprice', 'tradequantity', 'marketopen', 'marketclose', 'closeprice1d', 'closeprice', 'closequantity'].indexOf(obj) == -1;
3331
3381
  });
@@ -3351,7 +3401,7 @@ function Milli_Chart(settings) {
3351
3401
  var e = new Date();
3352
3402
  var days = 0;
3353
3403
  var newlen = 0;
3354
- while (days < _this.settings.intradaylen - 1) {
3404
+ while (days < _this.settings.intradaylen - 1) { // include today
3355
3405
  d -= 86400000;
3356
3406
  e.setTime(d);
3357
3407
  if (e.getDay() != 0 && e.getDay() != 6)
@@ -3394,7 +3444,6 @@ function Milli_Chart(settings) {
3394
3444
 
3395
3445
  (function updatePixelRatio() {
3396
3446
  matchMedia(`(resolution: ${window.devicePixelRatio}dppx)`).addEventListener('change', updatePixelRatio, { once: true });
3397
- () => {};
3398
3447
  _this.drawChart();
3399
3448
  })();
3400
3449
 
@@ -3405,7 +3454,7 @@ function Milli_Chart(settings) {
3405
3454
  }
3406
3455
  });
3407
3456
  }
3408
- var milli_data_api_url = 'https://stage.millistream.com/widgets/3.0.3/data/milli_widget_dataapi.php?';
3457
+ var milli_data_api_url = 'https://stage.millistream.com/widgets/3.0.4/data/milli_widget_dataapi.php?';
3409
3458
 
3410
3459
  var millistream_data_api = {
3411
3460
  callbackcounter: 0,
@@ -3453,14 +3502,14 @@ function MillistreamWidgetApi_buildQuery(widget, type) {
3453
3502
  if (typeof widget.settings.instrumenttype !== 'object') {
3454
3503
  throw new Error(widget.constructor.name + ': instrumenttype is not valid');
3455
3504
  }
3456
-
3505
+ //if (widget.settings.instrument == null) // removed 2021-10-12 for "mylist" functionality
3457
3506
  url += '&instrumenttypes=' + widget.settings.instrumenttype.join();
3458
3507
  }
3459
3508
  if (widget.settings.instrumentsubtype != null) {
3460
3509
  if (typeof widget.settings.instrumentsubtype !== 'object') {
3461
3510
  throw new Error(widget.constructor.name + ': instrumentsubtype is not valid');
3462
3511
  }
3463
-
3512
+ //if (widget.settings.instrument == null) // removed 2021-10-12 for "mylist" functionality
3464
3513
  url += '&instrumentsubtypes=' + widget.settings.instrumentsubtype.join();
3465
3514
  }
3466
3515
  if (widget.settings.derivativeindicator != null) {
@@ -3809,12 +3858,12 @@ function MillistreamWidgetApi_addPagination(widget) {
3809
3858
  li.onclick = function() {
3810
3859
  MillistreamWidgetApi_getPaginationPage(widget, 'next');
3811
3860
  };
3812
- if (widget.pagination.numPages < max + 1) li.style.display = 'none';
3861
+ if (widget.pagination.numPages < max + 1) li.style.display = 'none'; // dont show if less than 6 pages
3813
3862
  li = MillistreamWidgetApi_addElement(widget, 'li', 'millistream-list-pagination-li', widget.pagination.ul, null, '>>');
3814
3863
  li.onclick = function() {
3815
3864
  MillistreamWidgetApi_getPaginationPage(widget, 'last');
3816
3865
  };
3817
- if (widget.pagination.numPages < max + 1) li.style.display = 'none';
3866
+ if (widget.pagination.numPages < max + 1) li.style.display = 'none'; // dont show if less than 6 pages
3818
3867
  }
3819
3868
  } else
3820
3869
  if (widget.settings.pagination > 0 && widget.pagination.numPages < 2) {
@@ -3882,11 +3931,11 @@ function MillistreamWidgetApi_getPaginationPage(widget, page) {
3882
3931
  startno = 1;
3883
3932
  } else
3884
3933
  if (widget.pagination.selectedPage > widget.pagination.numPages - 2) {
3885
- startno = widget.pagination.numPages - (max - 1);
3934
+ startno = widget.pagination.numPages - (max - 1); //4;
3886
3935
 
3887
3936
  } else {
3888
3937
  startno = widget.pagination.selectedPage - 2 < 1 ? 1 : widget.pagination.selectedPage - (max - Math.ceil(max / 2));
3889
-
3938
+ //startno = widget.pagination.selectedPage - 1;
3890
3939
  }
3891
3940
  for (i = 2; i < items.length - 2; i++) {
3892
3941
  items[i].innerHTML = (startno);
@@ -3925,15 +3974,15 @@ function MillistreamWidgetApi_getElementHeight(el) {
3925
3974
  return rect.height + s;
3926
3975
  }
3927
3976
 
3928
-
3977
+ // Push blipp funktioner
3929
3978
  function MillistreamWidgetApi_clearFlash(el) {
3930
-
3979
+ //internal and external
3931
3980
  el.classList.remove('millistream-flash-up');
3932
3981
  el.classList.remove('millistream-flash-down');
3933
3982
  }
3934
3983
 
3935
3984
  function milli_clearValuedFlash(widget, el, oldValue) {
3936
-
3985
+ // internal borde gå att bygga bort
3937
3986
  var currentValue = MillistreamWidgetApi_getElementNumber(widget, el);
3938
3987
  if (currentValue == oldValue || currentValue == 0) {
3939
3988
  MillistreamWidgetApi_clearFlash(el);
@@ -3941,7 +3990,7 @@ function milli_clearValuedFlash(widget, el, oldValue) {
3941
3990
  }
3942
3991
 
3943
3992
  function MillistreamWidgetApi_flashElement(widget, el, newValue, oldValue) {
3944
-
3993
+ // internal
3945
3994
  if (newValue == oldValue) return;
3946
3995
  MillistreamWidgetApi_clearFlash(el);
3947
3996
  if (newValue == '' || !newValue) return;
@@ -3960,7 +4009,7 @@ function MillistreamWidgetApi_flashElement(widget, el, newValue, oldValue) {
3960
4009
  }
3961
4010
 
3962
4011
 
3963
-
4012
+ // numeriska funktioner
3964
4013
  function MillistreamWidgetApi_isNumber(widget, testsubject) {
3965
4014
  if (!testsubject) return;
3966
4015
  var n = testsubject.replace(widget.settings.decimalseparator, '.').split(widget.settings.thousandseparator).join('');
@@ -3973,7 +4022,7 @@ function MillistreamWidgetApi_getNumDecimals(widget, value, current, validfields
3973
4022
  if (value == null || MillistreamWidgetApi_isNumber(widget, value) == false) return current;
3974
4023
  var parts = value.toString().split('.');
3975
4024
  if (parts.length == 2) {
3976
- while (parts[1].charAt(parts[1].length - 1) == "0") {
4025
+ while (parts[1].charAt(parts[1].length - 1) == "0") { // remove trailing zeros
3977
4026
  parts[1] = parts[1].slice(0, -1);
3978
4027
  }
3979
4028
  return current > parts[1].length ? current : parts[1].length;
@@ -3982,7 +4031,7 @@ function MillistreamWidgetApi_getNumDecimals(widget, value, current, validfields
3982
4031
  }
3983
4032
 
3984
4033
  function MillistreamWidgetApi_getElementNumber(widget, el) {
3985
-
4034
+ // internal and Orderbook
3986
4035
  var res = parseFloat(el.innerHTML.replace(widget.settings.decimalseparator, '.').split(widget.settings.thousandseparator).join(''));
3987
4036
  if (!isNaN(parseFloat(res)) && isFinite(res)) return res;
3988
4037
  return 0;
@@ -4013,7 +4062,7 @@ function MillistreamWidgetApi_colorCell(widget, element, info) {
4013
4062
  MillistreamWidgetApi_setCellColor(widget, element, v);
4014
4063
  }
4015
4064
  } else
4016
- if (widget.settings.controlcolumn || widget.settings.controlcolumn == 0) {
4065
+ if (widget.settings.controlcolumn || widget.settings.controlcolumn == 0) { // works for tables
4017
4066
  if (widget.settings.stylecolumn === null) return;
4018
4067
  var tr = element.parentNode;
4019
4068
  while (tr.tagName.toLowerCase() != 'tr') {
@@ -4022,13 +4071,13 @@ function MillistreamWidgetApi_colorCell(widget, element, info) {
4022
4071
  if (tr.cells.length > widget.settings.controlcolumn) {
4023
4072
  v = MillistreamWidgetApi_getElementNumber(widget, tr.cells[widget.settings.controlcolumn]);
4024
4073
  var el;
4025
- if (widget.settings.stylecolumn && widget.settings.stylecolumn[0] == -1) {
4026
- el = tr;
4074
+ if (widget.settings.stylecolumn && widget.settings.stylecolumn[0] == -1) { // color row
4075
+ el = tr; //element.parentNode;
4027
4076
  MillistreamWidgetApi_setCellColor(widget, tr, v);
4028
4077
 
4029
4078
  } else {
4030
4079
  for (var s = 0; s < widget.settings.stylecolumn.length; s++) {
4031
- el = tr.cells[widget.settings.stylecolumn[s]];
4080
+ el = tr.cells[widget.settings.stylecolumn[s]]; //element.parentNode.cells[widget.stylecolumn[s]];
4032
4081
  if (el) {
4033
4082
  MillistreamWidgetApi_setCellColor(widget, el, v);
4034
4083
  }
@@ -4036,17 +4085,17 @@ function MillistreamWidgetApi_colorCell(widget, element, info) {
4036
4085
  }
4037
4086
  }
4038
4087
  } else
4039
- if (widget.settings.positiveclass && widget.settings.negativeclass) {
4088
+ if (widget.settings.positiveclass && widget.settings.negativeclass) { // non table elements
4040
4089
  v = MillistreamWidgetApi_getElementNumber(widget, element);
4041
4090
  MillistreamWidgetApi_setCellColor(widget, element, v);
4042
4091
  }
4043
4092
  }
4044
4093
 
4045
4094
  function print_field(widget, element, field, value, overridedecimals) {
4046
-
4095
+ // internal and external
4047
4096
  var f = parseInt(field);
4048
4097
  var info = MillistreamWidgetApi_getColumnInfo(widget, f.toString());
4049
- if (typeof value === 'undefined' || value == null || (!value && isNaN(value) == true)) {
4098
+ if (typeof value === 'undefined' || value == null || (!value && isNaN(value) == true)) { // kolla field?
4050
4099
  if (info[4] & 16) {
4051
4100
  value = '0.0';
4052
4101
  } else {
@@ -4092,7 +4141,7 @@ function print_field(widget, element, field, value, overridedecimals) {
4092
4141
  else
4093
4142
  element.innerHTML = formatFactorNumber(value, widget.settings.factor, widget.settings.num_decimals, widget.settings.thousandseparator, widget.settings.decimalseparator);
4094
4143
  } else if (info[4] & 4)
4095
- element.innerHTML = formatNiceNumber(value, widget.settings.thousandseparator, widget.settings.decimalseparator, 0);
4144
+ element.innerHTML = formatNiceNumber(value, widget.settings.thousandseparator, widget.settings.decimalseparator, 0); // no decimals
4096
4145
  else if (info[4] & 1 && overridedecimals)
4097
4146
  element.innerHTML = formatNiceNumber(value, widget.settings.thousandseparator, widget.settings.decimalseparator, overridedecimals || widget.settings.num_decimals);
4098
4147
  else {
@@ -4110,8 +4159,8 @@ function print_field(widget, element, field, value, overridedecimals) {
4110
4159
  }
4111
4160
 
4112
4161
  function MillistreamWidgetApi_getColumnInfo(widget, name) {
4113
-
4114
-
4162
+ // internal and external
4163
+ // return array with MDF_F_FIELD,type,align, name var, overridable decimal bitwise [1 = override output,2 = can override,4 = no decimals,8 can be shortened to M, K etc], 16 = override NULL with 0 , 32 = can color diff
4115
4164
  switch (name) {
4116
4165
  case '222':
4117
4166
  case 'accountsreceivable':
@@ -4202,7 +4251,7 @@ function MillistreamWidgetApi_getColumnInfo(widget, name) {
4202
4251
  return [232, 'numeric', 'right', widget.get_lang_text(name) || name, 8];
4203
4252
  case '404':
4204
4253
  case 'd1':
4205
- return [404, 'date', 'right', widget.get_lang_text(name) || name, 0];
4254
+ return [404, 'date', 'right', widget.get_lang_text(name) || name, 0]; // Security type
4206
4255
  case '3':
4207
4256
  case 'date':
4208
4257
  return [3, 'date', 'right', widget.get_lang_text(name) || name, 0];
@@ -4456,10 +4505,10 @@ function MillistreamWidgetApi_getColumnInfo(widget, name) {
4456
4505
  return [229, 'numeric', 'right', widget.get_lang_text(name) || name, 8];
4457
4506
  case '395':
4458
4507
  case 'n2':
4459
- return [395, 'numeric', 'left', widget.get_lang_text(name) || name, 0];
4508
+ return [395, 'numeric', 'left', widget.get_lang_text(name) || name, 0]; // Security type
4460
4509
  case '396':
4461
4510
  case 'n3':
4462
- return [396, 'numeric', 'left', widget.get_lang_text(name) || name, 0];
4511
+ return [396, 'numeric', 'left', widget.get_lang_text(name) || name, 0]; // Security type
4463
4512
  case '22':
4464
4513
  case 'name':
4465
4514
  return [22, 'string', 'left', widget.get_lang_text(name) || name, 0];
@@ -4471,10 +4520,10 @@ function MillistreamWidgetApi_getColumnInfo(widget, name) {
4471
4520
  return [138, 'numeric', 'right', widget.get_lang_text(name) || name, 8];
4472
4521
  case '48':
4473
4522
  case 'newsid':
4474
- return [48, 'string', 'left', 'newsid', 0];
4523
+ return [48, 'string', 'left', 'newsid', 0]; // hardoded should not be used by any display
4475
4524
  case 'newstype':
4476
4525
  case '86':
4477
- return [86, 'string', 'left', 'newstype', 0];
4526
+ return [86, 'string', 'left', 'newstype', 0]; // hardoded should not be used by any display
4478
4527
  case '219':
4479
4528
  case 'noncurrentasset':
4480
4529
  return [219, 'numeric', 'right', widget.get_lang_text(name) || name, 8];
@@ -4534,13 +4583,13 @@ function MillistreamWidgetApi_getColumnInfo(widget, name) {
4534
4583
  return [98, 'string', 'left', widget.get_lang_text(name) || name, 0];
4535
4584
  case '180':
4536
4585
  case 's3':
4537
- return [180, 'string', 'left', widget.get_lang_text(name) || name, 0];
4586
+ return [180, 'string', 'left', widget.get_lang_text(name) || name, 0]; // Position
4538
4587
  case '181':
4539
4588
  case 's4':
4540
- return [181, 'string', 'left', widget.get_lang_text(name) || name, 0];
4589
+ return [181, 'string', 'left', widget.get_lang_text(name) || name, 0]; // Position
4541
4590
  case '393':
4542
4591
  case 's10':
4543
- return [393, 'string', 'left', widget.get_lang_text(name) || name, 0];
4592
+ return [393, 'string', 'left', widget.get_lang_text(name) || name, 0]; // comment
4544
4593
  case '127':
4545
4594
  case 'sales':
4546
4595
  return [127, 'numeric', 'right', widget.get_lang_text(name) || name, 8];
@@ -4577,7 +4626,7 @@ function MillistreamWidgetApi_getColumnInfo(widget, name) {
4577
4626
  case '227':
4578
4627
  case 'totalassets':
4579
4628
  return [227, 'numeric', 'right', widget.get_lang_text(name) || name, 8];
4580
- case '1023':
4629
+ case '1023': // TODO, define this with correct value
4581
4630
  case 'totalnumberofshares':
4582
4631
  return [1023, 'numeric', 'right', widget.get_lang_text(name) || name, 8];
4583
4632
  case '233':
@@ -4626,7 +4675,7 @@ function MillistreamWidgetApi_getColumnInfo(widget, name) {
4626
4675
  case 'vega':
4627
4676
  return [703, 'numeric', 'right', widget.get_lang_text(name) || name, 0];
4628
4677
 
4629
-
4678
+ // brokerstats
4630
4679
  case '3000':
4631
4680
  case 'boughtquantity':
4632
4681
  return [3000, 'numeric', 'right', widget.get_lang_text(name) || name, 4];
@@ -4814,7 +4863,7 @@ function MillistreamWidgetApi_getColumnInfo(widget, name) {
4814
4863
  case '3060':
4815
4864
  case 'soldturnoverytd':
4816
4865
  return [3060, 'numeric', 'left', widget.get_lang_text(name) || name, 4];
4817
-
4866
+ // key ratios egen definerade
4818
4867
  case 'per_last':
4819
4868
  case '3100':
4820
4869
  return [3100, 'numeric', 'right', widget.get_lang_text(name) || name, 0];
@@ -4935,7 +4984,7 @@ function MillistreamWidgetApi_getColumnInfo(widget, name) {
4935
4984
  case 'latestreport':
4936
4985
  case '3140':
4937
4986
  return [3140, 'date', 'right', widget.get_lang_text(name) || name, 0];
4938
-
4987
+ // basicdata join fields
4939
4988
  case 'fundcompanyname':
4940
4989
  case '3200':
4941
4990
  return [3200, 'string', 'left', widget.get_lang_text(name) || name, 0];
@@ -4954,17 +5003,17 @@ function MillistreamWidgetApi_getColumnInfo(widget, name) {
4954
5003
  case '3205':
4955
5004
  case 'underlyingsymbol':
4956
5005
  return [3204, 'string', 'left', widget.get_lang_text(name) || name, 0];
4957
- case '3206':
5006
+ case '3206': // tmcwatch
4958
5007
  case 'multiplier':
4959
5008
  return [3206, 'string', 'left', widget.get_lang_text(name) || name, 0];
4960
- case '3207':
5009
+ case '3207': // tmcwach
4961
5010
  case 'type':
4962
5011
  return [3207, 'string', 'left', widget.get_lang_text(name) || name, 0];
4963
- case '3208':
5012
+ case '3208': // tmcwach
4964
5013
  case 'direction':
4965
5014
  return [3208, 'string', 'left', widget.get_lang_text(name) || name, 0];
4966
5015
 
4967
-
5016
+ // optionwatch
4968
5017
  case '3300':
4969
5018
  case 'iv30d':
4970
5019
  case 'ivXXd':
@@ -5007,8 +5056,8 @@ function MillistreamWidgetApi_getColumnInfo(widget, name) {
5007
5056
  }
5008
5057
  }
5009
5058
 
5010
- function set_hashed_element(widget, insref, info, json, num_dec) {
5011
-
5059
+ function set_hashed_element(widget, insref, info, json, num_dec) { // called from push
5060
+ // external : list
5012
5061
  var key = insref + '_' + info[0];
5013
5062
  var arr = widget.cell_map.get(key);
5014
5063
  if (arr !== undefined) {
@@ -5018,9 +5067,9 @@ function set_hashed_element(widget, insref, info, json, num_dec) {
5018
5067
  }
5019
5068
  }
5020
5069
 
5021
-
5070
+ // Create Element functions
5022
5071
  function MillistreamWidgetApi_addElementToMap(insref, field, element, widget) {
5023
-
5072
+ // internal
5024
5073
  if (insref && field && widget && widget.cell_map) {
5025
5074
  var key = insref + '_' + field;
5026
5075
  var arr = widget.cell_map.get(key);
@@ -5036,7 +5085,7 @@ function MillistreamWidgetApi_addElementToMap(insref, field, element, widget) {
5036
5085
  }
5037
5086
 
5038
5087
  function MillistreamWidgetApi_addElement(widget, el, cl, parent, field, value, overridedecimals) {
5039
-
5088
+ // external
5040
5089
  var element = document.createElement(el);
5041
5090
  if (cl)
5042
5091
  element.setAttribute('class', cl);
@@ -5119,7 +5168,7 @@ function MillistreamWidgetApi_addTableCell(widget, key, cl, parent, json, decima
5119
5168
  widget.settings.link_field.forEach(function(element) {
5120
5169
  hrefparam[element] = json[element];
5121
5170
  });
5122
- if (info[0] == 1) {
5171
+ if (info[0] == 1) { // headline, borde inte behövas i list
5123
5172
  td.onclick = function(e) {
5124
5173
  hrefparam.event = e;
5125
5174
  hrefparam.source = widget;
@@ -5235,7 +5284,7 @@ function fabs(value) {
5235
5284
  }
5236
5285
 
5237
5286
  function zeroPad(number, width) {
5238
-
5287
+ //internal
5239
5288
  if (number <= 9.9999999 * Math.pow(10, width)) return ("0000000" + number).slice(-width);
5240
5289
  return number;
5241
5290
  }
@@ -5280,7 +5329,7 @@ function formatNiceNumber(y, thousandSeparator, decimalSeparator, precision, add
5280
5329
  }
5281
5330
 
5282
5331
  function formatDate(date, format, widget) {
5283
-
5332
+ // internal
5284
5333
  var timeStamp, mon, day;
5285
5334
  if (format == 'yyyy-mm-dd') {
5286
5335
  timeStamp = new Date(date);
@@ -5294,66 +5343,66 @@ function formatDate(date, format, widget) {
5294
5343
  day = timeStamp.getDate();
5295
5344
  return timeStamp.getFullYear() % 100 + '-' + (mon <= 9 ? '0' + mon : mon) + '-' + (day <= 9 ? '0' + day : day);
5296
5345
  }
5297
- if (format == 'b dd') {
5346
+ if (format == 'b dd') { // Jan 01
5298
5347
  timeStamp = new Date(date);
5299
5348
  mon = timeStamp.toDateString().split(' ');
5300
5349
  day = timeStamp.getDate();
5301
5350
  return mon[1] + ' ' + (day <= 9 ? '0' + day : day);
5302
5351
  }
5303
- if (format == 'b dd yyyy') {
5352
+ if (format == 'b dd yyyy') { // Jan 01 2017
5304
5353
  timeStamp = new Date(date);
5305
5354
  mon = timeStamp.toDateString().split(' ');
5306
5355
  day = timeStamp.getDate();
5307
5356
  return mon[1] + ' ' + (day <= 9 ? '0' + day : day) + ' ' + timeStamp.getFullYear();
5308
5357
  }
5309
- if (format == 'dd/mm') {
5358
+ if (format == 'dd/mm') { // Jan 01 2017
5310
5359
  timeStamp = new Date(date);
5311
5360
  mon = timeStamp.getMonth() + 1;
5312
5361
  day = timeStamp.getDate();
5313
5362
  return (day <= 9 ? '0' + day : day) + '/' + (mon <= 9 ? '0' + mon : mon);
5314
5363
  }
5315
- if (format == 'd/m') {
5364
+ if (format == 'd/m') { // Jan 01 2017
5316
5365
  timeStamp = new Date(date);
5317
5366
  return (timeStamp.getDate() + '/' + (timeStamp.getMonth() + 1));
5318
5367
  }
5319
5368
  if (format == 'd mmm yyyy') {
5320
5369
  timeStamp = new Date(date);
5321
- mon = timeStamp.toLocaleString(widget.settings.locale, { month: 'short' }).substring(0, 3);
5370
+ mon = timeStamp.toLocaleString(widget.settings.locale, { month: 'short' }).substring(0, 3); // lang....
5322
5371
  day = timeStamp.getDate();
5323
5372
  return day + ' ' + mon + ' ' + timeStamp.getFullYear();
5324
5373
  }
5325
5374
  if (format == 'dd mmm yyyy') {
5326
5375
  timeStamp = new Date(date);
5327
- mon = timeStamp.toLocaleString(widget.settings.locale, { month: 'short' }).substring(0, 3);
5376
+ mon = timeStamp.toLocaleString(widget.settings.locale, { month: 'short' }).substring(0, 3); // lang....
5328
5377
  day = timeStamp.getDate();
5329
5378
  return (day <= 9 ? '0' + day : day) + ' ' + mon + ' ' + timeStamp.getFullYear();
5330
5379
  }
5331
5380
  if (format == 'dd mmm') {
5332
5381
  timeStamp = new Date(date);
5333
- mon = timeStamp.toLocaleString(widget.settings.locale, { month: 'short' }).substring(0, 3);
5382
+ mon = timeStamp.toLocaleString(widget.settings.locale, { month: 'short' }).substring(0, 3); // lang....
5334
5383
  day = timeStamp.getDate();
5335
5384
  return (day <= 9 ? '0' + day : day) + ' ' + mon;
5336
5385
  }
5337
5386
  if (format == 'd mmm') {
5338
5387
  timeStamp = new Date(date);
5339
- mon = timeStamp.toLocaleString(widget.settings.locale, { month: 'short' }).substring(0, 3);
5388
+ mon = timeStamp.toLocaleString(widget.settings.locale, { month: 'short' }).substring(0, 3); // lang....
5340
5389
  day = timeStamp.getDate();
5341
5390
  return day + ' ' + mon;
5342
5391
  }
5343
5392
  if (format == 'mmm yyyy') {
5344
5393
  timeStamp = new Date(date);
5345
- mon = timeStamp.toLocaleString(widget.settings.locale, { month: 'short' }).substring(0, 3);
5394
+ mon = timeStamp.toLocaleString(widget.settings.locale, { month: 'short' }).substring(0, 3); // lang....
5346
5395
  timeStamp = mon + ' ' + timeStamp.getFullYear();
5347
5396
  return timeStamp;
5348
5397
  }
5349
5398
  if (format == 'mmm yy') {
5350
5399
  timeStamp = new Date(date);
5351
- mon = timeStamp.toLocaleString(widget.settings.locale, { month: 'short' }).substring(0, 3);
5400
+ mon = timeStamp.toLocaleString(widget.settings.locale, { month: 'short' }).substring(0, 3); // lang
5352
5401
  timeStamp = mon + ' ' + (timeStamp.getFullYear() % 100 < 9 ? '0' + timeStamp.getFullYear() % 100 : timeStamp.getFullYear() % 100);
5353
5402
  return timeStamp;
5354
5403
  }
5355
5404
 
5356
-
5405
+ // default yyyy-mm-dd
5357
5406
  timeStamp = new Date(date);
5358
5407
  mon = timeStamp.getMonth() + 1;
5359
5408
  day = timeStamp.getDate();
@@ -5361,7 +5410,7 @@ function formatDate(date, format, widget) {
5361
5410
  }
5362
5411
 
5363
5412
  function formatTime(value, format) {
5364
-
5413
+ // internal
5365
5414
  if (typeof value !== 'string') return "";
5366
5415
  var datetime = new Date();
5367
5416
  var tz_offset = datetime.getTimezoneOffset();
@@ -5438,7 +5487,10 @@ Number.prototype.countDecimals = function() {
5438
5487
  //if (isNaN(this.valueOf()) || Math.floor(this.valueOf()) === this.valueOf()) return 0;
5439
5488
  if (isNaN(this.valueOf())) return 0;
5440
5489
  if (Math.floor(this.valueOf()) === this.valueOf()) return 0;
5441
- return this.toString().split(".")[1].length || 0;
5490
+ var parts = this.toString().split(".");
5491
+ if (parts.length > 1) return parts[1].length;
5492
+ return 0;
5493
+ //return this.toString().split(".")[1].length || 0;
5442
5494
  };
5443
5495
 
5444
5496
 
@@ -5590,7 +5642,7 @@ function MillistreamWidgetApi_scrollIntoView(scrollarea, elem, xalign, yalign) {
5590
5642
  scrollarea.scrollLeft = elem.offsetLeft - scrollarea.getBoundingClientRect().width / 2;
5591
5643
  }
5592
5644
 
5593
-
5645
+ // scrollIntoView : replace this, breaks apps
5594
5646
  }
5595
5647
 
5596
5648
  var MillistreamWidgetSettings = {
@@ -5610,9 +5662,9 @@ function MillistreamWidgetStreamingApi(settings) {
5610
5662
  server: 'wss://stage.millistream.com:8900',
5611
5663
  alarmClient: null
5612
5664
  };
5613
- var m_requestid = 1;
5665
+ var m_requestid = 1; // 0 is invalid
5614
5666
  var m_socket = null;
5615
- var m_requests = [];
5667
+ var m_requests = []; // queued requests not sent
5616
5668
  var m_requestcallbacks = new Map();
5617
5669
 
5618
5670
 
@@ -5645,7 +5697,7 @@ function MillistreamWidgetStreamingApi(settings) {
5645
5697
  req = new Object({
5646
5698
  "widget": widget,
5647
5699
  });
5648
- m_requestcallbacks.set(requestid.toString(), req);
5700
+ m_requestcallbacks.set(requestid.toString(), req); // this requestid will be forarded to this widget
5649
5701
  }
5650
5702
  var request = '';
5651
5703
  if (MillistreamWidgetApi_isObjectEmpty(widget.unsubscriptions) == false) {
@@ -5707,7 +5759,7 @@ function MillistreamWidgetStreamingApi(settings) {
5707
5759
 
5708
5760
 
5709
5761
  widget.unsubscriptions.type = 'insrefs';
5710
- widget.unsubscriptions.insrefs = insrefs.slice(0);
5762
+ widget.unsubscriptions.insrefs = insrefs.slice(0); // copy array
5711
5763
  widget.unsubscriptions.messagetypes = widget.settings.messagetypes;
5712
5764
  widget.unsubscriptions.requestid = requestid;
5713
5765
 
@@ -5720,7 +5772,7 @@ function MillistreamWidgetStreamingApi(settings) {
5720
5772
 
5721
5773
  function reconnect() {
5722
5774
  if (!m_socket.CLOSED) {
5723
-
5775
+ //console.log('not closed');
5724
5776
  return;
5725
5777
  }
5726
5778
  m_requests.forEach(function(request) {
@@ -5739,21 +5791,21 @@ function MillistreamWidgetStreamingApi(settings) {
5739
5791
  try {
5740
5792
  m_socket = new WebSocket(_this.settings.server);
5741
5793
  m_socket.onopen = function() {
5742
- () => {};
5794
+ console.log('Connected to millistream push'); /*RemoveLogging:skip*/
5743
5795
  if (m_requests.length > 0) {
5744
5796
  m_requests.forEach(function(request) {
5745
5797
  if (request.send == 0) {
5746
-
5798
+ //console.log('rerequest:', request.request);
5747
5799
  m_socket.send('{ "token":"' + _this.settings.token + '",' + request.request);
5748
5800
  }
5749
5801
  });
5750
5802
  }
5751
5803
  };
5752
5804
  m_socket.onerror = function() {
5753
- () => {};
5805
+ console.log('Error, disconnected'); /*RemoveLogging:skip*/
5754
5806
  };
5755
5807
  m_socket.onclose = function() {
5756
- () => {};
5808
+ console.log('Disconnected'); /*RemoveLogging:skip*/
5757
5809
  reconnect();
5758
5810
  };
5759
5811
 
@@ -5762,9 +5814,9 @@ function MillistreamWidgetStreamingApi(settings) {
5762
5814
  try {
5763
5815
  jsondata = JSON.parse(msg.data);
5764
5816
  } catch (e) {
5765
- () => {};
5817
+ console.log('invalid data', msg.data); /*RemoveLogging:skip*/
5766
5818
  }
5767
-
5819
+ //console.log(JSON.stringify(jsondata));
5768
5820
  if (typeof jsondata.instruments !== 'undefined') {
5769
5821
  for (var s = 0; s < jsondata.instruments.length; s++) {
5770
5822
  var insref = jsondata.instruments[s].insref;
@@ -5790,16 +5842,16 @@ function MillistreamWidgetStreamingApi(settings) {
5790
5842
  if (_this.settings.statusCallback !== null) _this.settings.statusCallback(jsondata);
5791
5843
  } else
5792
5844
  if (typeof jsondata.alarm !== 'undefined') {
5793
- () => {};
5845
+ console.log('Alarm: ' + JSON.stringify(jsondata));
5794
5846
  if (null != _this.settings.alarmClient) {
5795
5847
  _this.settings.alarmClient(jsondata);
5796
5848
  }
5797
5849
 
5798
5850
  } else
5799
- () => {};
5851
+ console.log(JSON.stringify(jsondata)); /*RemoveLogging:skip*/
5800
5852
  };
5801
5853
  } catch (exception) {
5802
- () => {};
5854
+ console.log('Exception error: ' + exception); /*RemoveLogging:skip*/
5803
5855
  reconnect();
5804
5856
  }
5805
5857
  }