@millistream/millistream-widgets 0.0.19 → 1.0.0

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.
@@ -1,6 +1,5 @@
1
- 'use strict';
2
-
3
1
  function Milli_Chart(settings) {
2
+ "use strict";
4
3
  var _this = this;
5
4
  _this.mdf_fields = [];
6
5
  _this.scaleinfoX = {};
@@ -8,38 +7,36 @@ function Milli_Chart(settings) {
8
7
  _this.scaleinfoY2 = {};
9
8
  _this.instruments = [];
10
9
  _this.settings = {
10
+ adjusted: true,
11
11
  autodraw: true,
12
- instrument: null,
13
- messagetypes: 4,
14
- onreadyCallback: null,
15
- streaming: false,
16
- target: null,
17
- startdate: null,
18
- startdateintraday: null,
12
+ chartlen: '1d',
19
13
  compress: 1,
20
-
21
14
  dateformat: 'd/m',
22
- timeformat: 'HH:mm',
23
- graphvalue: 'lastprice',
24
-
25
- intradaylen: null,
26
- historylen: null,
27
15
  drawxaxis: true, // TODO: 0 no, 1 yes, 2 yeas with markers (3px lines)
28
16
  drawyaxis: true,
29
17
  drawy2axis: false,
30
- //gridverticalLines: 2, // 0 off, 1 draw grid lines ,2 fillrect modulo
18
+ enablezoom: true,
19
+ fields: ['name', 'tradecurrency', 'time', 'date', 'tradeprice', 'tradequantity', 'marketopen', 'marketclose'],
20
+ fillchart: false,
21
+ gridVerticalLines: true, // 0 off, 1 draw grid lines ,2 fillrect modulo
22
+ gridVerticalLinesStyle: 'line',
31
23
  gridHorizontalLines: true,
32
24
  gridHorizontalLinesStyle: 'dash',
33
- chartlen: '1d',
34
- fillchart: false,
35
- fields: ['name', 'tradecurrency', 'time', 'date', 'tradeprice', 'tradequantity', 'marketopen', 'marketclose'],
36
- enablehover: true,
37
- enablezoom: true,
38
- intradaydates: false,
39
25
  hcurve: false,
40
- adjusted: true,
41
- nochartlabel: "No data to draw on",
42
- yearLabelsPos: 'bottom'
26
+ historylen: null,
27
+ instrument: null,
28
+ intradaydates: false,
29
+ intradaylen: null,
30
+ messagetypes: 4, // not a setting should always be 4 (trades)
31
+ nochartlabel: 'No data to draw on',
32
+ onreadyCallback: null,
33
+ startdate: null, // no setting, set in request code
34
+ //startdateintraday: null,
35
+ streaming: false,
36
+ target: null,
37
+ timeformat: 'HH:mm',
38
+ xhr: false,
39
+ yearLabelsPos: 'bottom',
43
40
  };
44
41
  _this.unsubscriptions = {};
45
42
  var m_chartspaces = {
@@ -62,14 +59,6 @@ function Milli_Chart(settings) {
62
59
  arr: [],
63
60
  map: new Map()
64
61
  };
65
- var m_tz_offset = 0;
66
- var m_yAxisPrecision = 0;
67
-
68
- var m_toolTip = {
69
- dateDiv: null,
70
- instrDiv: [],
71
- arrowDiv: []
72
- };
73
62
 
74
63
  var m_resizing = {
75
64
  resizing: false,
@@ -78,21 +67,6 @@ function Milli_Chart(settings) {
78
67
  drawing: false
79
68
  };
80
69
 
81
- var m_y2settings = {
82
- decimals: 2
83
- };
84
-
85
- var m_chartCss = {
86
- 'background-color': '#fffcf8',
87
- "margin-top": "20px",
88
- "margin-bottom": "30px",
89
- "margin-left": "40px",
90
- "margin-right": "40px",
91
- //"box-shadow": "2px 2px",
92
- "border-right-color": "#02020230", // box-shadow color
93
- "border-top-color": '#02020230' // box-shadow color
94
- };
95
-
96
70
  var m_zoom = {
97
71
  mousedown: {
98
72
  timestamp: null,
@@ -109,85 +83,93 @@ function Milli_Chart(settings) {
109
83
  };
110
84
  var m_lastDrawnInstrument = -1;
111
85
  var m_months = ['Jan', 'Feb', 'Mar', 'Apr', 'Maj', 'Jun', 'Jul', 'Aug', 'Sep', 'Okt', 'Nov', 'Dec'];
86
+
87
+ MillistreamWidgetApi_AssignObject(MillistreamWidgetSettings, _this.settings);
88
+ if (settings) {
89
+ MillistreamWidgetApi_AssignObject(settings, _this.settings);
90
+ }
91
+
92
+ var m_chartCss = {
93
+ backgroundColor: '#fffcf8',
94
+ marginTop: 0,
95
+ marginBottom: 0,
96
+ marginLeft: 0,
97
+ marginRight: 0
98
+ };
99
+ if (_this.settings.chartStyle) {
100
+ MillistreamWidgetApi_AssignObject(_this.settings.chartStyle, m_chartCss);
101
+ }
112
102
  var m_xLegendCss = {
113
- 'font-size': '10px',
114
- 'font-weight': 'bolder',
115
- 'font-style': 'normal',
116
- 'font-family': 'SuecaSans',
103
+ fontSize: '10px',
104
+ fontWeight: 'bolder',
105
+ fontFamily: 'SuecaSans',
117
106
  color: 'rgba(37, 45, 64, 0.24)'
118
107
  };
108
+ if (_this.settings.horizontalLegendStyle) {
109
+ MillistreamWidgetApi_AssignObject(_this.settings.horizontalLegendStyle, m_xLegendCss);
110
+ }
119
111
  var m_yLegendCss = {
120
- 'font-size': '10px',
121
- 'font-weight': 'bolder',
122
- 'font-style': 'normal',
123
- 'font-family': 'SuecaSans',
124
- 'font-variant': 'normal',
125
- 'color': 'rgba(37, 45, 64, 0.24)',
126
- float: 'right',
127
- "vertical-align": "top"
112
+ fontSize: '10px',
113
+ fontWeight: 'bolder',
114
+ fontFamily: 'SuecaSans',
115
+ color: 'rgba(37, 45, 64, 0.24)',
116
+ float: 'left',
117
+ verticalAlign: 'center',
118
+ textAlign: 'left'
128
119
  };
120
+ if (_this.settings.verticalLegendStyle) {
121
+ MillistreamWidgetApi_AssignObject(_this.settings.verticalLegendStyle, m_yLegendCss);
122
+ }
129
123
 
130
124
  var m_y2LegendCss = {
131
- 'font-size': '10px',
132
- 'font-weight': 'bold',
133
- 'font-style': 'normal',
134
- 'font-family': 'SuecaSans',
135
- 'font-variant': 'normal',
136
- 'color': 'rgba(37, 45, 64, 0.24)',
137
125
  float: "right",
138
- "vertical-align": "center"
139
126
  };
127
+ if (_this.settings.verticalLegend2Style) {
128
+ MillistreamWidgetApi_AssignObject(_this.settings.verticalLegend2Style, m_y2LegendCss);
129
+ }
130
+ var m_gridVerticalCss = {
131
+ color: 'rgba(37, 45, 64, 0.24)',
132
+ width: '5px'
133
+ };
134
+ if (_this.settings.verticalGridStyle) {
135
+ MillistreamWidgetApi_AssignObject(_this.settings.verticalGridStyle, m_gridVerticalCss);
136
+ }
137
+ var m_gridHorizontalCss = {
138
+ color: 'rgba(37, 45, 64, 0.24)',
139
+ };
140
+ if (_this.settings.horizontalGridStyle) {
141
+ MillistreamWidgetApi_AssignObject(_this.settings.horizontalGridStyle, m_gridHorizontalCss);
142
+ }
140
143
  var m_instrumentCss = [{
141
144
  color: '#E2507A',
142
- 'background-image': 'linear-gradient(rgba(226, 80, 122, 0.6),rgba(226, 80, 122, 0))',
143
- width: '2px'
145
+ //backgroundImage: 'linear-gradient(rgba(226, 80, 122, 0.6),rgba(226, 80, 122, 0))',
146
+ width: 1
144
147
  }, {
145
148
  color: '#ff0000',
146
- width: '1px'
149
+ width: 1
147
150
  }, {
148
151
  color: '#000000',
149
- width: '1px'
152
+ width: 1
150
153
  }, {
151
154
  color: '#00ff00',
152
- width: '1px'
155
+ width: 1
153
156
  }];
154
-
155
- var m_gridVerticalCss = {
156
- color: 'rgba(37, 45, 64, 0.24)',
157
- width: '1px'
158
- };
159
-
160
- var m_gridHorizontalCss = {
161
- color: 'rgba(37, 45, 64, 0.24)',
162
- width: '1px'
163
- };
164
-
165
- /* _this.cssClasses = {
166
- gridVertical: m_gridVerticalCss,
167
- xLegend: m_xLegendCss,
168
- chart: m_chartCss,
169
- instrument: m_instrumentCss
170
- }
171
- */
172
- MillistreamWidgetApi_AssignObject(MillistreamWidgetSettings, _this.settings);
173
- if (settings) {
174
- MillistreamWidgetApi_AssignObject(settings, _this.settings);
157
+ if (_this.settings.instrumentStyle) {
158
+ MillistreamWidgetApi_AssignObject(_this.settings.instrumentStyle, m_instrumentCss[0]);
159
+ }
160
+ if (_this.settings.compare1Style) {
161
+ MillistreamWidgetApi_AssignObject(_this.settings.compare1Style, m_instrumentCss[1]);
162
+ }
163
+ if (_this.settings.compare2Style) {
164
+ MillistreamWidgetApi_AssignObject(_this.settings.compare2Style, m_instrumentCss[2]);
165
+ }
166
+ if (_this.settings.compare3Style) {
167
+ MillistreamWidgetApi_AssignObject(_this.settings.compare3Style, m_instrumentCss[3]);
175
168
  }
176
169
 
177
170
  _this.get_lang_text = function(string) {
178
171
  return string;
179
172
  };
180
- // date and time functions
181
- /*function getWeekdays() {
182
- var startdate = new Date(_this.scaleinfoX.startTimeStamp);
183
- var days = 0;
184
- while (startdate.getTime() < _this.scaleinfoX.endTimeStamp) {
185
- if (startdate.getDay() != 0 && startdate.getDay() != 6)
186
- days++;
187
- startdate = new Date(startdate.getTime() + 86400000);
188
- }
189
- return days;
190
- }*/
191
173
 
192
174
  const isToday = (someDate) => {
193
175
  const today = new Date();
@@ -209,6 +191,19 @@ function Milli_Chart(settings) {
209
191
  // Discard the time and time-zone information.
210
192
  const utc1 = Date.UTC(a.getFullYear(), a.getMonth(), a.getDate());
211
193
  const utc2 = Date.UTC(b.getFullYear(), b.getMonth(), b.getDate());
194
+ /*var start = new Date(utc1);
195
+ var end = new Date(utc2);
196
+ var days = 0;
197
+ console.log(start, end, a, b);
198
+ while (start < end) {
199
+ console.log(start, end);
200
+ if (start.getDay() != 0 && start.getDay() != 6)
201
+ days++;
202
+ start = new Date(start.getTime() + 86400000);
203
+ }
204
+
205
+ console.log(days, Math.floor((utc2 - utc1) / 86400000));
206
+ return days;*/
212
207
  return Math.floor((utc2 - utc1) / 86400000); // ms per day
213
208
  }
214
209
 
@@ -251,7 +246,7 @@ function Milli_Chart(settings) {
251
246
  }
252
247
 
253
248
  function getFontSize(obj) {
254
- return parseInt(obj['font-size']);
249
+ return parseInt(obj.fontSize);
255
250
  }
256
251
 
257
252
  function getMaxTimeWidth() {
@@ -430,12 +425,14 @@ function Milli_Chart(settings) {
430
425
  firstvalue = parseFloat(_this.instruments[s].closeprice1d);
431
426
  }
432
427
  }
428
+ var quantity = 0;
433
429
  for (var i = 0; i < data.length; i++) {
434
430
  // only calc on visible data
435
- var price = data[i][_this.settings.graphvalue] * _this.instruments[s].factor;
436
- var quantity = 0;
437
- if (data[i].quantity !== 'undefined')
431
+ var price = data[i].price * _this.instruments[s].factor;
432
+ quantity = 0;
433
+ if (data[i].quantity !== 'undefined') {
438
434
  quantity = data[i].quantity;
435
+ }
439
436
  if (data[i].timestamp < _this.scaleinfoX.startTimeStamp) {
440
437
  continue;
441
438
  }
@@ -490,33 +487,45 @@ function Milli_Chart(settings) {
490
487
  function plotLower(valuePerPixel, lineLength) {
491
488
  m_ctx.save();
492
489
  m_ctx.strokeStyle = m_instrumentCss[0].color;
493
- m_ctx.lineWidth = parseInt(m_instrumentCss[0].width);
494
- m_ctx.beginPath();
490
+ m_ctx.lineWidth = m_instrumentCss[0].width;
495
491
  var width = Math.round(m_chartspaces.lowerChart.width / (m_datapoints.length + 1) / 2);
496
492
  if (width < 2) width = 2;
497
493
  else if (width > 20) width = 20;
498
494
  m_ctx.lineWidth = width;
499
495
  for (var i = 0; i < m_datapoints.length; i++) {
500
- var x = Math.round(m_datapoints[i].x);
501
- if (x - width < m_chartspaces.lowerChart.left) {
502
- x += width / 4;
496
+ var x = m_datapoints[i].x + 0.5;
497
+ m_ctx.lineWidth = width;
498
+ if (x - width <= m_chartspaces.lowerChart.left) {
503
499
  m_ctx.lineWidth = width / 2;
500
+ x += m_ctx.lineWidth / 2;
504
501
  } else
505
- if (x + width > m_chartspaces.lowerChart.right) {
506
- x -= width / 4;
502
+ if (x + width >= m_chartspaces.lowerChart.right) {
507
503
  m_ctx.lineWidth = width / 2;
504
+ x -= m_ctx.lineWidth / 2 + 1;
508
505
  }
509
-
510
- m_ctx.moveTo(x + 0.5, m_chartspaces.lowerChart.bottom);
511
- var y = Math.round(m_chartspaces.lowerChart.bottom - (m_datapoints[i].quantity * valuePerPixel));
512
- m_ctx.lineTo(x + 0.5, y);
506
+ m_ctx.beginPath();
507
+ m_ctx.moveTo(x, m_chartspaces.lowerChart.bottom - 0.5);
508
+ var y = Math.round(m_chartspaces.lowerChart.bottom - (m_datapoints[i].quantity * valuePerPixel)) - 1;
509
+ m_ctx.closePath();
510
+ m_ctx.lineTo(x, y - 0.5);
513
511
  m_ctx.stroke();
514
512
  }
515
- m_ctx.closePath();
516
513
  m_ctx.restore();
517
514
  }
518
515
 
519
516
  function drawYLegendLower(x, numticks, lineLength, markers) {
517
+ var i;
518
+ _this.scaleinfoY.lowLowerChart = null;
519
+ _this.scaleinfoY.highLowerChart = null;
520
+
521
+ for (i = 0; i < m_datapoints.length; i++) {
522
+ if (typeof m_datapoints[i].quantity !== 'undefined') {
523
+ if (_this.scaleinfoY.lowLowerChart == null || _this.scaleinfoY.lowLowerChart > m_datapoints[i].quantity) _this.scaleinfoY.lowLowerChart = m_datapoints[i].quantity;
524
+ if (_this.scaleinfoY.highLowerChart == null || _this.scaleinfoY.highLowerChart < m_datapoints[i].quantity) _this.scaleinfoY.highLowerChart = m_datapoints[i].quantity;
525
+ }
526
+ }
527
+ if (numticks < 1) return;
528
+ if (numticks > 10) numticks = 10;
520
529
  m_ctx.strokeStyle = m_gridHorizontalCss.color;
521
530
  m_ctx.fillStyle = m_yLegendCss.color;
522
531
 
@@ -529,7 +538,7 @@ function Milli_Chart(settings) {
529
538
  return false;
530
539
  }
531
540
  var value = 0;
532
- for (;;) {
541
+ for (i = 0; i < numticks; i++) {
533
542
  var y = Math.round(m_chartspaces.lowerChart.bottom - (value * valuePerPixel));
534
543
 
535
544
  if (y <= m_chartspaces.lowerChart.top) break;
@@ -539,21 +548,25 @@ function Milli_Chart(settings) {
539
548
  if (_this.settings.gridHorizontalLinesStyle == 'dash') {
540
549
  m_ctx.setLineDash([3, 3]);
541
550
  }
551
+ m_ctx.beginPath();
542
552
  m_ctx.moveTo(m_chartspaces.lowerChart.left, y + 0.5);
543
553
  m_ctx.lineTo(m_chartspaces.lowerChart.right, y + 0.5);
544
554
  m_ctx.stroke();
555
+ m_ctx.closePath();
545
556
  m_ctx.restore();
546
557
  } else
547
558
  if (_this.settings.drawyaxis == true && markers == true) { // draw legenditem markers for price
559
+ m_ctx.beginPath();
548
560
  m_ctx.moveTo(m_chartspaces.lowerChart.left, y + 0.5);
549
561
  m_ctx.lineTo(m_chartspaces.lowerChart.left + 3, y + 0.5);
550
562
  m_ctx.stroke();
563
+ m_ctx.closePath();
551
564
  }
552
565
 
553
566
  if (markers == true && _this.settings.drawyaxis == true) {
554
567
  var label = formatLargeNumber(value, 0, _this);
555
568
  var textpos = x - 5;
556
- if (m_yLegendCss['vertical-align'] == 'top') {
569
+ if (m_yLegendCss.verticalAlign == 'top') {
557
570
  if (y - (getFontSize(m_yLegendCss)) > 0) // dont draw if cropped
558
571
  m_ctx.fillText(label, textpos, y - ((getFontSize(m_yLegendCss) + 2)));
559
572
  } else
@@ -567,29 +580,30 @@ function Milli_Chart(settings) {
567
580
  }
568
581
 
569
582
  function drawYAxisLower() {
570
- //m_ctx.save();
571
- m_ctx.strokeStyle = m_gridHorizontalCss.color;
572
- m_ctx.font = m_yLegendCss['font-weight'] + ' ' + m_yLegendCss['font-size'] + ' ' + m_yLegendCss['font-family'];
583
+ m_ctx.save();
584
+ m_ctx.font = m_yLegendCss.fontWeight + ' ' + m_yLegendCss.fontSize + ' ' + m_yLegendCss.fontFamily;
573
585
  m_ctx.fillStyle = m_yLegendCss.color;
574
586
  var lineLen = m_chartspaces.lowerChart.bottom - m_chartspaces.lowerChart.top;
575
587
  var numticks = lineLen / (getFontSize(m_yLegendCss) * 2);
576
588
  if (numticks > 8) numticks = 8; // limit to 8 items on Y legend ( this is not an absolut count, since we calculate nice legend numbers
577
589
 
590
+ m_ctx.beginPath();
591
+ m_ctx.strokeStyle = m_gridVerticalCss.color;
578
592
  m_ctx.moveTo(m_chartspaces.lowerChart.left + 0.5, m_chartspaces.lowerChart.top);
579
593
  m_ctx.lineTo(m_chartspaces.lowerChart.left + 0.5, m_chartspaces.lowerChart.bottom);
580
594
  m_ctx.stroke();
595
+ m_ctx.closePath();
596
+ //m_ctx.strokeStyle = m_gridHorizontalCss.color;
581
597
  var x = m_chartspaces.lowerChart.left - 3;
582
-
583
598
  drawYLegendLower(x, numticks, lineLen, true);
584
- //m_ctx.restore();
585
-
599
+ m_ctx.restore();
586
600
  }
587
601
 
588
602
  function drawYLegend(si, x, side, gridHorizontalLines, number) {
589
603
  var value;
590
604
  si.maxValue = si.highValue + (si.tickSize * 0.2);
591
605
  si.minValue = si.lowValue - (si.tickSize * 0.2);
592
- m_ctx.font = m_yLegendCss['font-weight'] + ' ' + m_yLegendCss['font-size'] + ' ' + m_yLegendCss['font-family'];
606
+ m_ctx.font = m_yLegendCss.fontWeight + ' ' + m_yLegendCss.fontSize + ' ' + m_yLegendCss.fontFamily;
593
607
  if (si.highValue == si.lowValue) { // only have one value so set values for 1 line only
594
608
  si.maxValue = si.maxValue + si.tickSize;
595
609
  si.minValue = si.minValue - si.tickSize;
@@ -640,12 +654,12 @@ function Milli_Chart(settings) {
640
654
  if ((number == 1 && _this.settings.drawyaxis == true) || (number == 2 && _this.settings.drawy2axis == true)) {
641
655
  var label;
642
656
  if (number == 2)
643
- label = formatNiceNumber(value, _this.settings.thousandseparator, _this.settings.decimalseparator, si.decimals, true);
657
+ label = formatNiceNumber(value, _this.settings.thousandseparator, _this.settings.decimalseparator, si.decimals, true) + '%';
644
658
  else
645
659
  label = formatNiceNumber(value, _this.settings.thousandseparator, _this.settings.decimalseparator, si.decimals, false);
646
660
  var textpos = x - 5;
647
661
  if (side == 'right') textpos = x + 7;
648
- if (m_yLegendCss['vertical-align'] == 'top') {
662
+ if (m_yLegendCss.verticalAlign == 'top') {
649
663
  if (y - (getFontSize(m_yLegendCss)) > 0) // dont draw if cropped
650
664
  m_ctx.fillText(label, textpos, y - ((getFontSize(m_yLegendCss) + 2)));
651
665
  } else
@@ -660,7 +674,7 @@ function Milli_Chart(settings) {
660
674
  function drawYAxis() {
661
675
  m_ctx.save();
662
676
  m_ctx.strokeStyle = m_gridHorizontalCss.color;
663
- m_ctx.font = m_yLegendCss['font-weight'] + ' ' + m_yLegendCss['font-size'] + ' ' + m_yLegendCss['font-family'];
677
+ m_ctx.font = m_yLegendCss.fontWeight + ' ' + m_yLegendCss.fontSize + ' ' + m_yLegendCss.fontFamily;
664
678
  m_ctx.fillStyle = m_yLegendCss.color;
665
679
  //if (_this.settings.chartlen == '1d' || _this.settings.chartlen == '0d') firstvalue = _this.instruments[0].closeprice1d;
666
680
 
@@ -680,7 +694,7 @@ function Milli_Chart(settings) {
680
694
  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å?
681
695
  m_chartspaces.lowerChart.left = m_chartspaces.chart.left;
682
696
  } else {
683
- if (m_yLegendCss['text-align'] == 'right') {
697
+ if (m_yLegendCss.textAlign == 'right') {
684
698
  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å?
685
699
  m_chartspaces.lowerChart.right = m_chartspaces.chart.right;
686
700
  }
@@ -696,7 +710,7 @@ function Milli_Chart(settings) {
696
710
  label = formatNiceNumber(_this.scaleinfoY2.highValue, _this.settings.thousandseparator, _this.settings.decimalseparator, _this.scaleinfoY2.decimals) + ' %';
697
711
  if (m_y2LegendCss.float != 'right') {
698
712
  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å?
699
- m_chartspaces.lowerChart.left = m_chartspaces.chart.left
713
+ m_chartspaces.lowerChart.left = m_chartspaces.chart.left;
700
714
  } else {
701
715
  // kolla setting om den skall vara "i diagrammet"
702
716
  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å?
@@ -705,19 +719,21 @@ function Milli_Chart(settings) {
705
719
  }
706
720
  if (m_yLegendCss.float != 'right' && _this.settings.drawyaxis) {
707
721
  m_ctx.save();
708
- m_ctx.font = m_xLegendCss['font-weight'] + ' ' + m_xLegendCss['font-size'] + ' ' + m_xLegendCss['font-family'];
722
+ m_ctx.font = m_xLegendCss.fontWeight + ' ' + m_xLegendCss.fontSize + ' ' + m_xLegendCss.fontFamily;
709
723
  if (getStringWidth(m_ctx, _this.settings.dateformat) / 2 + 5 > m_chartspaces.chart.left) m_chartspaces.chart.left = getStringWidth(m_ctx, _this.settings.dateformat) / 2 + 5;
710
724
  m_ctx.restore();
711
725
  }
726
+ m_ctx.strokeStyle = m_gridVerticalCss.color;
712
727
  m_ctx.beginPath();
713
728
  m_ctx.moveTo(m_chartspaces.chart.left + 0.5, m_chartspaces.chart.top);
714
- m_ctx.lineTo(m_chartspaces.chart.left + 0.5, m_chartspaces.chart.height - parseInt(m_chartCss['margin-bottom']));
729
+ m_ctx.lineTo(m_chartspaces.chart.left + 0.5, m_chartspaces.chart.height - m_chartCss.marginBottom);
715
730
  m_ctx.stroke();
716
731
  m_ctx.closePath();
732
+ m_ctx.strokeStyle = m_gridHorizontalCss.color;
717
733
 
718
734
  var x;
719
735
  if (m_yLegendCss.float == 'right') {
720
- if (m_yLegendCss['text-align'] == 'right')
736
+ if (m_yLegendCss.textAlign == 'right')
721
737
  x = m_chartspaces.chart.right;
722
738
  else
723
739
  x = m_chartspaces.chart.right + 3;
@@ -726,7 +742,7 @@ function Milli_Chart(settings) {
726
742
  }
727
743
 
728
744
  m_ctx.textAlign = 'right';
729
- if (m_yLegendCss['text-align'] == 'right') {
745
+ if (m_yLegendCss.textAlign == 'right') {
730
746
  m_ctx.textAlign = 'left';
731
747
  drawYLegend(_this.scaleinfoY, x, 'right', _this.settings.gridHorizontalLines, 1);
732
748
  } else
@@ -746,10 +762,10 @@ function Milli_Chart(settings) {
746
762
  function drawXAxisGridlines(p, newday) {
747
763
  // draws the vertical grid or dots
748
764
  m_ctx.save();
749
- m_ctx.strokeStyle = m_gridHorizontalCss.color;
750
- if (_this.settings.gridVerticalLines > 0) {
765
+ m_ctx.strokeStyle = m_gridVerticalCss.color;
766
+ if (_this.settings.gridVerticalLines) {
751
767
  if (_this.settings.drawy2axis == false || p.x != m_chartspaces.chart.left) {
752
- if (_this.settings.gridHorizontalLinesStyle == 'dash') {
768
+ if (_this.settings.gridVerticalLinesStyle == 'dash') {
753
769
  m_ctx.setLineDash([3, 3]);
754
770
  }
755
771
  if (newday) m_ctx.setLineDash([3, 3]);
@@ -833,15 +849,15 @@ function Milli_Chart(settings) {
833
849
  function drawXAxisYears(starttime, endtime) {
834
850
  if (getNumberOfDays(starttime, endtime) < 366) return drawXAxisMonth(starttime, endtime);
835
851
  m_ctx.save();
836
- m_ctx.font = m_xLegendCss['font-weight'] + ' ' + m_xLegendCss['font-size'] + ' ' + m_xLegendCss['font-family'];
837
- m_ctx.strokeStyle = m_gridHorizontalCss.color;
852
+ m_ctx.font = m_xLegendCss.fontWeight + ' ' + m_xLegendCss.fontSize + ' ' + m_xLegendCss.fontFamily;
853
+ m_ctx.strokeStyle = m_gridVerticalCss.color;
838
854
  m_ctx.fillStyle = m_xLegendCss.color;
839
855
  m_ctx.textAlign = "left";
840
856
  calcXScale(starttime, endtime);
841
857
  if (_this.settings.drawxaxis != 0) {
842
858
  m_ctx.beginPath();
843
- m_ctx.moveTo(m_chartspaces.chart.left, m_chartspaces.chart.height - parseInt(m_chartCss['margin-bottom']) + 0.5);
844
- m_ctx.lineTo(m_chartspaces.chart.right, m_chartspaces.chart.height - parseInt(m_chartCss['margin-bottom']) + 0.5);
859
+ m_ctx.moveTo(m_chartspaces.chart.left, m_chartspaces.chart.height - m_chartCss.marginBottom + 0.5);
860
+ m_ctx.lineTo(m_chartspaces.chart.right, m_chartspaces.chart.height - m_chartCss.marginBottom + 0.5);
845
861
  m_ctx.stroke();
846
862
  m_ctx.closePath();
847
863
  }
@@ -859,8 +875,8 @@ function Milli_Chart(settings) {
859
875
  }
860
876
  }
861
877
  if (draw) {
862
- //drawXAxisGridlines({ 'x': x, y: m_canvas.height - parseInt(m_chartCss['margin-bottom']) });
863
- drawXAxisGridlines({ 'x': x, y: m_chartspaces.chart.height - parseInt(m_chartCss['margin-bottom']) });
878
+ //drawXAxisGridlines({ 'x': x, y: m_canvas.height - m_chartCss.marginBottom });
879
+ drawXAxisGridlines({ 'x': x, y: m_chartspaces.chart.height - m_chartCss.marginBottom });
864
880
  text = year;
865
881
  if (_this.scaleinfoX.lineLength + m_chartspaces.chart.left > x - m_ctx.measureText(text).width) { // not to far right?
866
882
  if (_this.settings.yearLabelsPos == 'top') {
@@ -873,8 +889,8 @@ function Milli_Chart(settings) {
873
889
  m_ctx.fillText(text, 0, 0);
874
890
  m_ctx.restore();
875
891
  } else {
876
- //m_ctx.fillText(text, x - (m_ctx.measureText(text).width / 2), m_canvas.height - parseInt(m_chartCss['margin-bottom']) + 10);
877
- m_ctx.fillText(text, x - (m_ctx.measureText(text).width / 2), m_chartspaces.chart.height - parseInt(m_chartCss['margin-bottom']) + 10);
892
+ //m_ctx.fillText(text, x - (m_ctx.measureText(text).width / 2), m_canvas.height - m_chartCss.marginBottom + 10);
893
+ m_ctx.fillText(text, x - (m_ctx.measureText(text).width / 2), m_chartspaces.chart.height - m_chartCss.marginBottom + 10);
878
894
  }
879
895
  }
880
896
  numItems++;
@@ -898,12 +914,10 @@ function Milli_Chart(settings) {
898
914
  }
899
915
  }
900
916
  if (draw) {
901
- //drawXAxisGridlines({ 'x': x, y: m_canvas.height - parseInt(m_chartCss['margin-bottom']) });
902
- drawXAxisGridlines({ 'x': x, y: m_chartspaces.chart.height - parseInt(m_chartCss['margin-bottom']) });
917
+ drawXAxisGridlines({ 'x': x, y: m_chartspaces.chart.height - m_chartCss.marginBottom });
903
918
  text = formatDate(year.getFullYear() + '-07-01', _this.settings.dateformat);
904
919
  // ingen if som på year???
905
- //m_ctx.fillText(text, x - (m_ctx.measureText(text).width / 2), m_canvas.height - parseInt(m_chartCss['margin-bottom']) + 10);
906
- m_ctx.fillText(text, x - (m_ctx.measureText(text).width / 2), m_chartspaces.chart.height - parseInt(m_chartCss['margin-bottom']) + 10);
920
+ m_ctx.fillText(text, x - (m_ctx.measureText(text).width / 2), m_chartspaces.chart.height - m_chartCss.marginBottom + 10);
907
921
  numItems++;
908
922
  legendItems.push({ 'text': text, timestamp: new Date(year + '-07-01T00:00:00Z'), 'x': x });
909
923
  }
@@ -928,11 +942,9 @@ function Milli_Chart(settings) {
928
942
  }
929
943
  if (dontPrint) break;
930
944
  if (draw) {
931
- //drawXAxisGridlines({ 'x': x, y: m_canvas.height - parseInt(m_chartCss['margin-bottom']) });
932
- drawXAxisGridlines({ 'x': x, y: m_chartspaces.chart.height - parseInt(m_chartCss['margin-bottom']) });
945
+ drawXAxisGridlines({ 'x': x, y: m_chartspaces.chart.height - m_chartCss.marginBottom });
933
946
  text = formatDate(year.getFullYear() + '-' + (year.getMonth() + 1) + '-01', _this.settings.dateformat);
934
- //m_ctx.fillText(text, x - (m_ctx.measureText(text).width / 2), m_canvas.height - parseInt(m_chartCss['margin-bottom']) + 10);
935
- m_ctx.fillText(text, x - (m_ctx.measureText(text).width / 2), m_chartspaces.height - parseInt(m_chartCss['margin-bottom']) + 10);
947
+ m_ctx.fillText(text, x - (m_ctx.measureText(text).width / 2), m_chartspaces.chart.height - m_chartCss.marginBottom + 10);
936
948
  }
937
949
  legendItems.push({ 'text': text, timestamp: new Date(year + '-04-01T00:00:00Z'), 'x': x });
938
950
  year = new Date((year.getFullYear() + 1) + '-04-01T00:00:00Z');
@@ -951,11 +963,9 @@ function Milli_Chart(settings) {
951
963
  }
952
964
  }
953
965
  if (draw) {
954
- //drawXAxisGridlines({ 'x': x, y: m_canvas.height - parseInt(m_chartCss['margin-bottom']) });
955
- drawXAxisGridlines({ 'x': x, y: m_chartspaces.chart.height - parseInt(m_chartCss['margin-bottom']) });
966
+ drawXAxisGridlines({ 'x': x, y: m_chartspaces.chart.height - m_chartCss.marginBottom });
956
967
  text = formatDate(year.getFullYear() + '-' + (year.getMonth() + 1) + '-01', _this.settings.dateformat);
957
- //m_ctx.fillText(text, x - (m_ctx.measureText(text).width / 2), m_canvas.height - parseInt(m_chartCss['margin-bottom']) + 10);
958
- m_ctx.fillText(text, x - (m_ctx.measureText(text).width / 2), m_chartspaces.chart.height - parseInt(m_chartCss['margin-bottom']) + 10);
968
+ m_ctx.fillText(text, x - (m_ctx.measureText(text).width / 2), m_chartspaces.chart.height - m_chartCss.marginBottom + 10);
959
969
  }
960
970
  legendItems.push({ 'text': text, timestamp: new Date(year + '-10-01T00:00:00Z'), 'x': x });
961
971
  year = new Date((year.getFullYear() + 1) + '-10-01T00:00:00Z');
@@ -970,14 +980,14 @@ function Milli_Chart(settings) {
970
980
  starttime -= starttime % 8640000;
971
981
  endtime -= starttime % 8640000;
972
982
  m_ctx.save();
973
- m_ctx.font = m_xLegendCss['font-weight'] + ' ' + m_xLegendCss['font-size'] + ' ' + m_xLegendCss['font-family'];
974
- m_ctx.strokeStyle = m_gridHorizontalCss.color;
983
+ m_ctx.font = m_xLegendCss.fontWeight + ' ' + m_xLegendCss.fontSize + ' ' + m_xLegendCss.fontFamily;
984
+ m_ctx.strokeStyle = m_gridVerticalCss.color;
975
985
  m_ctx.fillStyle = m_xLegendCss.color;
976
986
  calcXScale(starttime, endtime);
977
987
  if (_this.settings.drawxaxis != 0) { // draw line
978
988
  m_ctx.beginPath();
979
- m_ctx.moveTo(m_chartspaces.chart.left, m_chartspaces.chart.height - parseInt(m_chartCss['margin-bottom']) + 0.5);
980
- m_ctx.lineTo(m_chartspaces.chart.right, m_chartspaces.chart.height - parseInt(m_chartCss['margin-bottom']) + 0.5);
989
+ m_ctx.moveTo(m_chartspaces.chart.left, m_chartspaces.chart.height - m_chartCss.marginBottom + 0.5);
990
+ m_ctx.lineTo(m_chartspaces.chart.right, m_chartspaces.chart.height - m_chartCss.marginBottom + 0.5);
981
991
  m_ctx.stroke();
982
992
  m_ctx.closePath();
983
993
  }
@@ -1012,10 +1022,8 @@ function Milli_Chart(settings) {
1012
1022
  currentDate = new Date(currentDate.getTime() + 86400000);
1013
1023
  }
1014
1024
  // vad är detta?
1015
- if (typeof m_chartCss.boxShadow !== 'undefined') {
1016
- var boxshadow = m_chartCss.boxShadow.split(' ');
1017
- if (parseInt(boxshadow[1]) == 0) drawXAxisGridlines({ 'x': x, y: m_chartspaces.chart.bottom }, false);
1018
-
1025
+ if (typeof m_chartCss.boxShadow !== 'undefined' && typeof m_chartCss.boxShadow.rightWidth !== 'undefined') {
1026
+ if (m_chartCss.boxShadow.rightWidth == 0) drawXAxisGridlines({ 'x': x, y: m_chartspaces.chart.bottom }, false);
1019
1027
  } else {
1020
1028
  drawXAxisGridlines({ 'x': x, y: m_chartspaces.chart.bottom }, false);
1021
1029
  }
@@ -1089,12 +1097,10 @@ function Milli_Chart(settings) {
1089
1097
  // internal
1090
1098
  if (typeof value !== 'string') return "";
1091
1099
  var datetime = new Date();
1092
- //var tz_offset = datetime.getTimezoneOffset();
1093
1100
  datetime.setHours(parseInt(value));
1094
1101
  datetime.setMinutes(parseInt(value.substring(3)));
1095
1102
  datetime.setSeconds(parseInt(value.substring(6)));
1096
1103
  datetime = datetime.getTime();
1097
- //datetime -= tz_offset * 60000; // tz_offset in minutes
1098
1104
  datetime = new Date(datetime);
1099
1105
  switch (format) {
1100
1106
  case 'HH:mm':
@@ -1122,8 +1128,9 @@ function Milli_Chart(settings) {
1122
1128
  }
1123
1129
 
1124
1130
  function drawXAxisTickLowerChart() {
1131
+
1125
1132
  m_ctx.save();
1126
- m_ctx.font = m_xLegendCss['font-weight'] + ' ' + m_xLegendCss['font-size'] + ' ' + m_xLegendCss['font-family'];
1133
+ m_ctx.font = m_xLegendCss.fontWeight + ' ' + m_xLegendCss.fontSize + ' ' + m_xLegendCss.fontFamily;
1127
1134
 
1128
1135
  m_ctx.strokeStyle = m_gridHorizontalCss.color;
1129
1136
  m_ctx.fillStyle = m_xLegendCss.color;
@@ -1138,10 +1145,11 @@ function Milli_Chart(settings) {
1138
1145
  }
1139
1146
 
1140
1147
  function drawXAxisTick(starttime, endtime) {
1148
+ // in unixtime
1141
1149
  m_ctx.save();
1142
- m_ctx.font = m_xLegendCss['font-weight'] + ' ' + m_xLegendCss['font-size'] + ' ' + m_xLegendCss['font-family'];
1150
+ m_ctx.font = m_xLegendCss.fontWeight + ' ' + m_xLegendCss.fontSize + ' ' + m_xLegendCss.fontFamily;
1143
1151
 
1144
- m_ctx.strokeStyle = m_gridHorizontalCss.color;
1152
+ m_ctx.strokeStyle = m_gridVerticalCss.color;
1145
1153
  m_ctx.fillStyle = m_xLegendCss.color;
1146
1154
  m_ctx.textAlign = "left";
1147
1155
  calcXScaleTick(starttime, endtime);
@@ -1152,6 +1160,7 @@ function Milli_Chart(settings) {
1152
1160
  m_ctx.stroke();
1153
1161
  m_ctx.closePath();
1154
1162
  }
1163
+ var dayLightChange = (new Date(starttime).getTimezoneOffset() - new Date().getTimezoneOffset()) * 60000;
1155
1164
  var currentDate = new Date(starttime);
1156
1165
  var x;
1157
1166
  var lastx = 0;
@@ -1185,6 +1194,17 @@ function Milli_Chart(settings) {
1185
1194
  if (_this.scaleinfoX.lineLength + m_chartspaces.chart.left > x - getMaxTimeWidth()) { // not to far right?
1186
1195
  m_ctx.fillText(text, x - (m_ctx.measureText(text).width / 2), m_chartspaces.chart.bottom + 10);
1187
1196
  legendItems.push({ x: x, type: 0, text: text });
1197
+ if (_this.settings.intradaydates) { // draw dates on top
1198
+ m_ctx.save();
1199
+ var date = currentDate.getDate() + '/' + (currentDate.getMonth() + 1);
1200
+ var fontMetrix = m_ctx.measureText(date);
1201
+ var dx = x + fontMetrix.actualBoundingBoxAscent + fontMetrix.actualBoundingBoxDescent + 3;
1202
+ var dy = m_chartCss.marginTop; // + m_ctx.measureText(datum).width;
1203
+ m_ctx.translate(dx, dy);
1204
+ m_ctx.rotate(90 * Math.PI / 180);
1205
+ m_ctx.fillText(date, 0, 0);
1206
+ m_ctx.restore();
1207
+ }
1188
1208
  }
1189
1209
  if (x != m_chartspaces.chart.left + 0.5) { // do not draw the first line, it is already drawn
1190
1210
  if (openhour == currentDate.getTime() % 86400000) {
@@ -1203,7 +1223,7 @@ function Milli_Chart(settings) {
1203
1223
  }
1204
1224
  }
1205
1225
  // add timestamps
1206
- var currentDate = new Date(starttime);
1226
+ currentDate = new Date(starttime);
1207
1227
  if (currentDate.getTime() % 3600000 != 0) // if not full hour, move up to next full hour
1208
1228
  currentDate = new Date(currentDate.getTime() - currentDate.getTime() % 3600000 + 3600000); // START om full hour (if modulo == 0 then + 3600000 kanske)
1209
1229
 
@@ -1228,7 +1248,7 @@ function Milli_Chart(settings) {
1228
1248
  if (days == 1) {
1229
1249
  // use start and endtime as ticksize
1230
1250
  tickSize = new Date(endtime - starttime);
1231
- } else if (m_zoom.mouseup.timestamp && days == 2) { // zoom with more than 2 days
1251
+ } else if (m_zoom.mouseup.timestamp && days == 2) { // zoom with 2 days
1232
1252
  // use the day with most time as tickSize
1233
1253
  var tmpDate = new Date(starttime);
1234
1254
  tickSize = new Date(new Date(tmpDate.toISOString().substring(0, 10) + 'T' + _this.instruments[0].marketclose + 'Z') - new Date(starttime)).getTime();
@@ -1262,13 +1282,21 @@ function Milli_Chart(settings) {
1262
1282
  tickSize = tickSize.getTime() / 3600000;
1263
1283
  interval = Math.floor(tickSize / (maxHourLegends + 1)) * 3600000;
1264
1284
  }
1265
- if (interval == 0) interval = 300000;
1266
- if (interval % 60000 != 0)
1285
+ if (interval == 0) {
1286
+ // default 1h
1287
+ interval = 3600000;
1288
+ modularvalue = 3600000;
1289
+ }
1290
+ if (interval % 60000 != 0) {
1267
1291
  interval = (interval - interval % 60000) + 60000; // remove sekunder
1292
+ }
1268
1293
  // print other times
1269
1294
  offset = 0;
1270
1295
  lastx = 0;
1271
1296
  var closeTime = new Date(currentDate.toISOString().substring(0, 10) + 'T' + _this.instruments[0].marketclose + 'Z');
1297
+ dayLightChange = (closeTime.getTimezoneOffset() - new Date().getTimezoneOffset()) * 60000;
1298
+ closeTime = new Date(closeTime.getTime() - dayLightChange);
1299
+
1272
1300
  var workDate = new Date(currentDate);
1273
1301
  currentDate = new Date(starttime);
1274
1302
  if (currentDate.getTime() % modularvalue != 0) // if not full hour, move up to next full hour
@@ -1276,28 +1304,31 @@ function Milli_Chart(settings) {
1276
1304
 
1277
1305
  var count = 0;
1278
1306
  while (currentDate.getTime() <= _this.scaleinfoX.endTimeStamp) {
1307
+ dayLightChange = (closeTime.getTimezoneOffset() - new Date().getTimezoneOffset()) * 60000;
1279
1308
  if (count++ > 100) {
1280
1309
  break; // just make sure we dont do an infinity loop
1281
1310
 
1282
1311
  }
1283
1312
  draw = true;
1284
1313
  while (currentDate.getDay() == 0 || currentDate.getDay() == 6) { // move past weekends , maybe skip this if date is available in data
1285
- closeTime = new Date(closeTime.getTime() + 86400000);
1314
+ //closeTime = new Date(closeTime.getTime() + 86400000);
1286
1315
  currentDate = new Date(currentDate.getTime() + 86400000);
1316
+ closeTime = new Date(currentDate.toISOString().substring(0, 10) + 'T' + _this.instruments[0].marketclose + 'Z');
1287
1317
  if (currentDate.getTime() % modularvalue != 0) // if not full hour, move up to next full hour
1288
1318
  currentDate = new Date(currentDate.getTime() - currentDate.getTime() % modularvalue + modularvalue); // START om full hour (if modulo == 0 then + 3600000 kanske)
1289
- var workDate = new Date(workDate.getTime() + 86400000);
1319
+ workDate = new Date(workDate.getTime() + 86400000);
1290
1320
  offset += 86400000 / _this.scaleinfoX.timePerPixel;
1291
1321
  }
1292
1322
  if (currentDate.getTime() > closeTime.getTime()) {
1293
1323
  // draw DayEnd(start) dash line
1294
- var dayStart = new Date(workDate.toISOString().substring(0, 10) + 'T' + _this.instruments[0].marketclose + 'Z')
1324
+ var dayStart = new Date(workDate.toISOString().substring(0, 10) + 'T' + _this.instruments[0].marketclose + 'Z');
1295
1325
  x = Math.round(m_chartspaces.chart.left + ((dayStart.getTime() - _this.scaleinfoX.startDate.getTime()) / _this.scaleinfoX.timePerPixel) - offset);
1296
1326
  drawXAxisGridlines({ 'x': x, y: m_chartspaces.chart.bottom }, true); // dash?
1297
1327
 
1298
1328
  closeTime = new Date(closeTime.getTime() + 86400000);
1299
1329
  workDate = new Date(workDate.getTime() + 86400000);
1300
1330
  currentDate = new Date(workDate.toISOString().substring(0, 10) + 'T' + _this.instruments[0].marketopen + 'Z');
1331
+
1301
1332
  if (currentDate.getTime() % modularvalue != 0) // if not full hour, move up to next full hour
1302
1333
  currentDate = new Date(currentDate.getTime() - currentDate.getTime() % modularvalue + modularvalue); // START om full hour (if modulo == 0 then + 3600000 kanske)
1303
1334
  offset += (86400000 - _this.scaleinfoX.milliPerDay) / _this.scaleinfoX.timePerPixel;
@@ -1321,12 +1352,12 @@ function Milli_Chart(settings) {
1321
1352
  if (lastx + (getMaxTimeWidth() / 2) > (x - getMaxTimeWidth())) {
1322
1353
  //draw = false;
1323
1354
  }
1324
- var text = formatChartTime(currentDate.toTimeString().substring(0, 8), _this.settings.timeformat);
1325
1355
  if (draw) {
1326
1356
  lastx = x;
1327
1357
  // if day change and setting print on top as well
1328
1358
  if (_this.scaleinfoX.lineLength + m_chartspaces.chart.left > x - getMaxTimeWidth()) { // not to far right?
1329
- m_ctx.fillText(text, x - (m_ctx.measureText(text).width / 2), m_chartspaces.chart.bottom + 10);
1359
+ var label = formatChartTime(currentDate.toTimeString().substring(0, 8), _this.settings.timeformat);
1360
+ m_ctx.fillText(label, x - (m_ctx.measureText(label).width / 2), m_chartspaces.chart.bottom + 10);
1330
1361
  legendItems.push({ x: x, type: 0 });
1331
1362
  }
1332
1363
  drawXAxisGridlines({ 'x': x, y: m_chartspaces.chart.bottom }, false);
@@ -1335,9 +1366,8 @@ function Milli_Chart(settings) {
1335
1366
  }
1336
1367
 
1337
1368
  // vad är detta?
1338
- if (typeof m_chartCss.boxShadow !== 'undefined') {
1339
- var boxshadow = m_chartCss.boxShadow.split(' ');
1340
- if (parseInt(boxshadow[1]) == 0) drawXAxisGridlines({ 'x': x, y: m_chartspaces.chart.bottom }, false);
1369
+ if (typeof m_chartCss.boxShadow !== 'undefined' && typeof m_chartCss.boxShadow.rightWidth !== 'undefined') {
1370
+ if (m_chartCss.boxShadow.rightWidth == 0) drawXAxisGridlines({ 'x': x, y: m_chartspaces.chart.bottom }, false);
1341
1371
 
1342
1372
  } else {
1343
1373
  drawXAxisGridlines({ 'x': x, y: m_chartspaces.chart.bottom }, false);
@@ -1346,22 +1376,14 @@ function Milli_Chart(settings) {
1346
1376
  }
1347
1377
 
1348
1378
  function onMouseOut(evt) {
1349
- if (m_toolTip.dateDiv) {
1350
- m_toolTip.dateDiv.parentNode.removeChild(m_toolTip.dateDiv);
1351
- m_toolTip.dateDiv = null;
1352
- }
1353
- for (var i = 0; i < m_toolTip.instrDiv.length; i++) {
1354
- if (m_toolTip.instrDiv[i]) {
1355
- m_toolTip.instrDiv[i].parentNode.removeChild(m_toolTip.instrDiv[i]);
1356
- m_toolTip.instrDiv[i] = null;
1357
- }
1358
- if (m_toolTip.arrowDiv[i]) {
1359
- m_toolTip.arrowDiv[i].parentNode.removeChild(m_toolTip.arrowDiv[i]);
1360
- m_toolTip.arrowDiv[i] = null;
1379
+ for (var i = 0; i < _this.instruments.length; i++) {
1380
+ if (_this.instruments[i].insref != 0 && typeof _this.instruments[i].toolTip !== 'undefined') {
1381
+ _this.instruments[i].toolTip.parentNode.removeChild(_this.instruments[i].toolTip);
1382
+ _this.instruments[i].toolTipPointer.parentNode.removeChild(_this.instruments[i].toolTipPointer);
1383
+ _this.instruments[i].toolTip = undefined;
1384
+ _this.instruments[i].toolTipPointer = undefined;
1361
1385
  }
1362
1386
  }
1363
- m_toolTip.instrDiv = [];
1364
- m_toolTip.arrowDiv = [];
1365
1387
  }
1366
1388
 
1367
1389
  function clearZoom() {
@@ -1385,16 +1407,18 @@ function Milli_Chart(settings) {
1385
1407
  m_zoom.div = document.createElement('div');
1386
1408
  m_canvas.parentNode.appendChild(m_zoom.div);
1387
1409
  m_zoom.div.setAttribute('class', 'millistream-chart-zoombox');
1410
+ m_zoom.div.style.pointerEvents = 'none';
1411
+ m_zoom.div.style.position = 'absolute';
1388
1412
  }
1389
1413
  if (x < m_chartspaces.chart.left) x = m_chartspaces.chart.left;
1390
1414
  m_zoom.div.style.top = m_chartspaces.chart.top + 'px';
1391
1415
  m_zoom.div.style.left = (m_zoom.mousedown.pos > x ? x : m_zoom.mousedown.pos) + 'px';
1392
1416
  if (x > m_chartspaces.chart.right) x = m_chartspaces.chart.right;
1393
- m_zoom.div.style.height = m_chartspaces.chart.height - parseInt(m_chartCss['margin-bottom']) - m_chartspaces.chart.top + 'px';
1417
+ m_zoom.div.style.height = m_chartspaces.chart.height - m_chartCss.marginBottom - m_chartspaces.chart.top + 'px';
1394
1418
  m_zoom.div.style.width = (m_zoom.mousedown.pos > x ? m_zoom.mousedown.pos - x : x - m_zoom.mousedown.pos) + 'px';
1395
1419
  }
1396
- if (_this.settings.enablehover == false) return;
1397
- if (x < m_chartspaces.chart.left || x > m_chartspaces.chart.right || y < m_chartspaces.chart.top || y > m_chartspaces.chart.height - parseInt(m_chartCss['margin-bottom'])) {
1420
+ if (typeof _this.settings.tooltip != 'object' || typeof _this.settings.tooltip.formatter != 'function') return;
1421
+ if (x < m_chartspaces.chart.left || x > m_chartspaces.chart.right || y < m_chartspaces.chart.top || y > m_chartspaces.chart.height - m_chartCss.marginBottom) {
1398
1422
  onMouseOut();
1399
1423
  return;
1400
1424
  }
@@ -1413,134 +1437,71 @@ function Milli_Chart(settings) {
1413
1437
  if (obj == null) {
1414
1438
  return;
1415
1439
  }
1416
- // datetime
1417
- if (m_toolTip.dateDiv == null) {
1418
- m_toolTip.dateDiv = document.createElement('div');
1419
- m_canvas.parentNode.appendChild(m_toolTip.dateDiv);
1420
- }
1421
- var d = new Date(obj.timestamp);
1422
- m_toolTip.dateDiv.innerHTML = zeroPad(d.getFullYear(), 2);
1423
- m_toolTip.dateDiv.innerHTML += '-' + zeroPad(d.getMonth() + 1, 2);
1424
- m_toolTip.dateDiv.innerHTML += '-' + zeroPad(d.getDate(), 2) + '&nbsp'; // fixa dateformatet
1425
- if (_this.settings.chartlen != 'ytd' && _this.settings.chartlen.charAt(_this.settings.chartlen.length - 1) == 'd') { // TODO: change to tickchart
1426
- m_toolTip.dateDiv.innerHTML += zeroPad(d.getHours(), 2);
1427
- m_toolTip.dateDiv.innerHTML += ':' + zeroPad(d.getMinutes(), 2);
1428
- m_toolTip.dateDiv.innerHTML += ':' + zeroPad(d.getSeconds(), 2);
1429
- }
1430
- m_toolTip.dateDiv.innerHTML += 'X:' + x;
1431
- m_toolTip.dateDiv.setAttribute('class', 'millistream-chart-tooltip'); // set class so we can measure it might change below depending on position
1432
- m_toolTip.dateDiv.style.left = m_dataPoints.arr[i] + 'px'; // TODO: räkna ut 7 px beroende på hur hoverpilen ser ut från höjden på diven
1433
-
1434
- // prices
1435
- var highy = -1000;
1436
- var lowy = 1000000; // hmm
1437
- var priceorder = [];
1438
- var num = 0;
1439
- for (x = 0; x < _this.instruments.length; x++) {
1440
- if (typeof m_toolTip.instrDiv[x] === 'undefined') {
1441
- m_toolTip.instrDiv[x] = document.createElement('div');
1442
- m_canvas.parentNode.appendChild(m_toolTip.instrDiv[x]);
1443
- }
1444
- if (typeof obj.instruments[x] === 'undefined') {
1445
- m_toolTip.instrDiv[x].style.display = 'none';
1446
- continue;
1447
- }
1448
- m_toolTip.instrDiv[x].style.display = 'block';
1449
- priceorder[num] = {};
1450
- priceorder[num].price = obj.instruments[x].price * _this.instruments[x].factor;
1451
- priceorder[num].instrument = x;
1452
- num++;
1453
- }
1454
- if (priceorder.length > 1) {
1455
- priceorder.sort(function(a, b) {
1456
- return b.price - a.price;
1457
- });
1458
- }
1459
- var keys = Object.keys(priceorder);
1460
- var left = 0;
1461
- for (x = 0; x < keys.length; x++) {
1462
- var k = priceorder[x].instrument;
1463
- if (typeof obj.instruments[k] !== 'undefined') {
1464
- var posy = obj.instruments[k].y - 7;
1440
+ var highy = -1;
1441
+ var lowy = m_chartspaces.height;
1442
+ for (var x = 0; x < _this.instruments.length; x++) {
1443
+ if (_this.instruments[x].insref != 0 && typeof obj.instruments[x] !== 'undefined') {
1444
+ var instr = {};
1445
+ instr.chartType = _this.scaleinfoY.type;
1446
+ instr.name = _this.instruments[x].name;
1447
+ if (typeof _this.instruments[x].symbol !== 'undefined')
1448
+ instr.symbol = _this.instruments[x].symbol;
1449
+
1450
+ instr.data = {};
1451
+ MillistreamWidgetApi_AssignObject(obj.instruments[x], instr.data);
1452
+ instr.data.price = formatNiceNumber(instr.data.price, _this.settings.thousandseparator, _this.settings.decimalseparator, _this.settings.num_decimals, false);
1453
+
1454
+ var ttip = _this.settings.tooltip.formatter.call(instr);
1455
+ if (typeof _this.instruments[x].toolTip === 'undefined') {
1456
+ // add textdiv
1457
+ _this.instruments[x].toolTip = document.createElement('div');
1458
+ _this.instruments[x].toolTip.style.display = 'block';
1459
+ _this.instruments[x].toolTip.setAttribute('class', 'millistream-chart-tooltip'); // set class so we can measure it might change below depending on position
1460
+ _this.instruments[x].toolTip.position = 'absolute';
1461
+ m_canvas.parentNode.appendChild(_this.instruments[x].toolTip);
1462
+ // add pointer div
1463
+ _this.instruments[x].toolTipPointer = document.createElement('div');
1464
+ m_canvas.parentNode.appendChild(_this.instruments[x].toolTipPointer);
1465
+ _this.instruments[x].toolTipPointer.setAttribute('class', 'millistream-chart-pointer');
1466
+ _this.instruments[x].toolTipPointer.style.left = (m_dataPoints.arr[i] - (_this.instruments[x].toolTipPointer.clientWidth / 2)) + 'px';
1467
+ _this.instruments[x].toolTipPointer.style.top = (obj.instruments[x].y - (_this.instruments[x].toolTipPointer.clientHeight / 2)) + 'px';
1468
+ _this.instruments[x].toolTipPointer.style.position = 'absolute';
1469
+ _this.instruments[x].toolTipPointer.style.backgroundColor = m_instrumentCss[x].color;
1470
+ _this.instruments[x].toolTipPointer.style.pointerEvents = 'none';
1471
+
1472
+ }
1473
+ var pointerStyle = getComputedStyle(_this.instruments[x].toolTipPointer);
1474
+ var pointerWidth = _this.instruments[x].toolTipPointer.offsetWidth + parseInt(pointerStyle.marginLeft) + parseInt(pointerStyle.marginRight);
1475
+ var pointerHeight = _this.instruments[x].toolTipPointer.offsetHeight + parseInt(pointerStyle.marginTop) + parseInt(pointerStyle.marginBottom);
1476
+ _this.instruments[x].toolTip.innerHTML = ttip;
1477
+ var posy = obj.instruments[x].y - (_this.instruments[x].toolTip.offsetHeight / 2);
1465
1478
  var tmp = Math.abs(posy - parseFloat(highy));
1466
- if (tmp < 30) {
1467
- posy = parseFloat(highy) + 20;
1479
+ var height = _this.instruments[x].toolTip.offsetHeight;
1480
+ if (tmp < height) {
1481
+ posy = parseFloat(highy) + height;
1468
1482
  }
1469
1483
  tmp = Math.abs(posy - parseFloat(lowy));
1470
1484
  if (tmp < 30) {
1471
1485
  // hur gör vi här? behövs det när vi sätter dom i ordning?
1472
1486
  //posy = parseFloat(highy) + 20;
1473
1487
  }
1474
- m_toolTip.instrDiv[k].innerHTML = formatNiceNumber(obj.instruments[k].price, _this.settings.thousandseparator, _this.settings.decimalseparator, obj.instruments[k].price.countDecimals());
1475
- if (typeof obj.instruments[k].diff !== 'undefined') m_toolTip.instrDiv[k].innerHTML += ', diff:' + formatNiceNumber(obj.instruments[k].diff, ' ', ',', m_y2settings.decimals);
1476
- m_toolTip.instrDiv[k].setAttribute('class', 'millistream-chart-tooltip'); // set class so we can measure it might change below depending on position
1477
- m_toolTip.instrDiv[k].style.top = posy + 'px'; // TODO: räkna ut 7 px beroende på hur hoverpilen ser ut från höjden på diven depending on position
1478
- if (m_dataPoints.arr[i] + m_toolTip.instrDiv[k].offsetWidth + 10 > m_canvas.width || m_dataPoints.arr[i] + m_toolTip.dateDiv.offsetWidth + 10 > m_canvas.width) { // TODO +10 should be calculated better
1488
+ 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
1479
1489
  // draw the hover to the left
1480
- m_toolTip.instrDiv[k].setAttribute('class', 'millistream-chart-tooltip');
1481
- m_toolTip.instrDiv[k].style.left = (m_dataPoints.arr[i] - m_toolTip.instrDiv[k].offsetWidth - 10) + 'px'; // - parseInt(m_tooltipLeftCss['border-left-width']) + 'px';
1490
+ _this.instruments[x].toolTip.style.left = (m_dataPoints.arr[i] - _this.instruments[x].toolTip.offsetWidth - (pointerWidth / 2)) + 1 + 'px';
1482
1491
  } else {
1483
1492
  // draw hover to the right
1484
- m_toolTip.instrDiv[k].style.left = (m_dataPoints.arr[i] + 10) + 'px'; //+ parseInt(m_tooltipLeftCss['border-left-width']) - 1 + 'px';
1485
- m_toolTip.instrDiv[k].setAttribute('class', 'millistream-chart-tooltip');
1486
- }
1487
- left = m_toolTip.instrDiv[k].style.left;
1488
- //m_toolTip.instrDiv[x].style.display = 'block';
1489
- //m_toolTip.instrDiv[x].style.height = '14px';
1490
- // draw arrow
1491
- var arrow = false;
1492
- var color;
1493
- if (arrow) {
1494
- if (typeof m_toolTip.arrowDiv[k] === 'undefined') {
1495
- m_toolTip.arrowDiv[k] = document.createElement('div');
1496
- m_canvas.parentNode.appendChild(m_toolTip.arrowDiv[k]);
1497
- }
1498
- var thickness = 2;
1499
- var x1 = m_dataPoints.arr[i];
1500
- var x2 = parseInt(m_toolTip.instrDiv[k].style.left);
1501
- var y1 = obj.instruments[k].y;
1502
- var y2 = parseInt(m_toolTip.instrDiv[k].style.top) + (parseInt(m_toolTip.instrDiv[k].style.height) / 2);
1503
- var length = Math.sqrt(((x2 - x1) * (x2 - x1)) + ((y2 - y1) * (y2 - y1)));
1504
- var cx = ((x1 + x2) / 2) - (length / 2);
1505
- var cy = ((y1 + y2) / 2) - (thickness / 2);
1506
- // angle
1507
- var angle = Math.atan2((y1 - y2), (x1 - x2)) * (180 / Math.PI);
1508
- color = m_instrumentCss[k].color;
1509
- m_toolTip.arrowDiv[k].style.padding = '0px';
1510
- m_toolTip.arrowDiv[k].style.margin = '0px';
1511
- m_toolTip.arrowDiv[k].style.height = thickness + 'px';
1512
- m_toolTip.arrowDiv[k].style.backgroundColor = color;
1513
- m_toolTip.arrowDiv[k].style.lineHeight = '1px';
1514
- m_toolTip.arrowDiv[k].style.position = 'absolute';
1515
- m_toolTip.arrowDiv[k].style.left = cx + 'px';
1516
- m_toolTip.arrowDiv[k].style.top = cy + 'px';
1517
- m_toolTip.arrowDiv[k].style.width = length + 'px';
1518
- m_toolTip.arrowDiv[k].style.pointerEvents = 'none';
1519
- m_toolTip.arrowDiv[k].style.transform = 'rotate(' + angle + 'deg)';
1520
- } else {
1521
- if (typeof m_toolTip.arrowDiv[k] === 'undefined') {
1522
- m_toolTip.arrowDiv[k] = document.createElement('div');
1523
- m_canvas.parentNode.appendChild(m_toolTip.arrowDiv[k]);
1524
- }
1525
- m_toolTip.arrowDiv[k].setAttribute('class', 'millistream-chart-pointer');
1526
- m_toolTip.arrowDiv[k].style.left = (m_dataPoints.arr[i] - (m_toolTip.arrowDiv[k].clientWidth / 2)) + 'px';
1527
- m_toolTip.arrowDiv[k].style.top = (obj.instruments[k].y - (m_toolTip.arrowDiv[k].clientHeight / 2)) + 'px';
1528
- m_toolTip.arrowDiv[k].style.position = 'absolute';
1529
- color = m_instrumentCss[k].color;
1530
- m_toolTip.arrowDiv[k].style.backgroundColor = color;
1531
- m_toolTip.arrowDiv[k].style.pointerEvents = 'none';
1493
+ _this.instruments[x].toolTip.style.left = (obj.instruments[x].x + (pointerWidth / 2)) + 'px';
1532
1494
  }
1495
+ _this.instruments[x].toolTip.style.top = posy + 'px';
1496
+
1497
+ _this.instruments[x].toolTipPointer.style.left = (obj.instruments[x].x - (pointerWidth / 2)) + 1 + 'px'; // hmm plus 1??
1498
+ _this.instruments[x].toolTipPointer.style.top = (obj.instruments[x].y - (pointerHeight / 2)) + 'px';
1533
1499
  if (posy > highy) highy = posy;
1534
1500
  if (posy < lowy) lowy = posy;
1535
- } else {
1536
- console.log('No instrument error');
1501
+
1537
1502
  }
1538
1503
  }
1539
- if (m_toolTip.instrDiv.length > 0) {
1540
- m_toolTip.dateDiv.style.left = left;
1541
- m_toolTip.dateDiv.style.top = parseInt(m_toolTip.instrDiv[0].style.top) - m_toolTip.dateDiv.offsetHeight - 5 + 'px'; // datepos
1542
- m_toolTip.dateDiv.style.top = lowy - m_toolTip.dateDiv.offsetHeight - 5 + 'px'; // datepos
1543
- }
1504
+ return;
1544
1505
  }
1545
1506
 
1546
1507
  function setTimeSpanData() {
@@ -1559,33 +1520,13 @@ function Milli_Chart(settings) {
1559
1520
  enddate = enddate.replaceAll('\/', '-');
1560
1521
  m_zoom.mousedown.timestamp = new Date(startdate + 'T00:00:00Z');
1561
1522
  m_zoom.mouseup.timestamp = new Date(enddate + 'T00:00:00Z');
1562
- // _this.scaleinfoX.endTimeStamp = m_zoom.mouseup.timestamp > m_zoom.mousedown.timestamp ? m_zoom.mouseup.timestamp : m_zoom.mousedown.timestamp;
1563
- // _this.scaleinfoX.startTimeStamp = m_zoom.mouseup.timestamp < m_zoom.mousedown.timestamp ? m_zoom.mouseup.timestamp : m_zoom.mousedown.timestamp;
1564
1523
  _this.drawChart();
1565
1524
  };
1566
1525
 
1567
1526
  function calcCompareFactors(type) {
1568
1527
  var i, s;
1569
- if (type == 'history2') {
1570
- if (_this.instruments.length > 1) {
1571
- if (_this.instruments[s].insref != 0) {
1572
- for (i = 0; i < _this.instruments[0].history.length; i++) {
1573
- if (_this.instruments[0].history[i].timestamp >= _this.scaleinfoX.startTimeStamp) {
1574
- instrumentprice = _this.instruments[0].history[i].price;
1575
- break;
1576
- }
1577
- }
1578
- for (s = 1; s < _this.instruments.length; s++) {
1579
- for (i = 0; i < _this.instruments[s].history.length; i++) {
1580
- if (_this.instruments[s].history[i].timestamp >= _this.scaleinfoX.startTimeStamp) {
1581
- _this.instruments[s].factor = instrumentprice / _this.instruments[s].history[i].price;
1582
- break;
1583
- }
1584
- }
1585
- }
1586
- }
1587
- }
1588
- }
1528
+ var instrumentprice;
1529
+
1589
1530
  if (_this.instruments.length > 1) {
1590
1531
  for (s = 1; s < _this.instruments.length; s++) {
1591
1532
  if (_this.instruments[s].insref != 0) {
@@ -1607,7 +1548,6 @@ function Milli_Chart(settings) {
1607
1548
  }
1608
1549
 
1609
1550
  function checkChartData(data) {
1610
- // _this.instruments[0].history / _this.instruments[0].trades
1611
1551
  var count = 0;
1612
1552
  for (var i = 0; i < data.length; i++) {
1613
1553
  if (data[i].timestamp >= _this.scaleinfoX.startTimeStamp && data[i].timestamp <= _this.scaleinfoX.endTimeStamp) {
@@ -1620,8 +1560,8 @@ function Milli_Chart(settings) {
1620
1560
  var y = m_chartspaces.chart.bottom - m_chartspaces.chart.top / 2 + m_chartspaces.chart.top;
1621
1561
  var x = m_chartspaces.chart.right - m_chartspaces.chart.left / 2 + m_chartspaces.chart.left;
1622
1562
  m_ctx.save();
1623
- m_ctx.font = 'bold ' + m_xLegendCss['font-size'] + ' ' + m_xLegendCss['font-family'];
1624
- m_ctx.font = 'bold 12px ' + m_xLegendCss['font-family'];
1563
+ m_ctx.font = 'bold ' + m_xLegendCss.fontSize + ' ' + m_xLegendCss.fontFamily;
1564
+ m_ctx.font = 'bold 12px ' + m_xLegendCss.fontFamily;
1625
1565
  m_ctx.strokeStyle = m_gridHorizontalCss.color;
1626
1566
  m_ctx.fillStyle = m_xLegendCss.color;
1627
1567
  m_ctx.textAlign = "left";
@@ -1633,16 +1573,16 @@ function Milli_Chart(settings) {
1633
1573
 
1634
1574
  function calcChartSpaces() {
1635
1575
  m_chartspaces.chart.height = Math.round(m_canvas.height * (m_chartspaces.chart.percent / 100));
1636
- m_chartspaces.chart.top = parseInt(m_chartCss['margin-top']);
1637
- m_chartspaces.chart.left = parseInt(m_chartCss['margin-left']);
1638
- m_chartspaces.chart.right = m_canvas.width - parseInt(m_chartCss['margin-right']);
1639
- m_chartspaces.chart.bottom = m_chartspaces.chart.height - parseInt(m_chartCss['margin-bottom']);
1576
+ m_chartspaces.chart.top = m_chartCss.marginTop;
1577
+ m_chartspaces.chart.left = m_chartCss.marginLeft;
1578
+ m_chartspaces.chart.right = m_canvas.width - m_chartCss.marginRight;
1579
+ m_chartspaces.chart.bottom = m_chartspaces.chart.height - m_chartCss.marginBottom;
1640
1580
  m_chartspaces.chart.width = m_canvas.width;
1641
1581
  m_chartspaces.lowerChart.height = m_canvas.height * (m_chartspaces.lowerChart.percent / 100);
1642
- m_chartspaces.lowerChart.top = Math.round(m_chartspaces.chart.bottom + parseInt(m_chartCss['margin-bottom']) + m_chartspaces.chart.top);
1582
+ m_chartspaces.lowerChart.top = Math.round(m_chartspaces.chart.bottom + m_chartCss.marginBottom + m_chartspaces.chart.top);
1643
1583
  m_chartspaces.lowerChart.left = m_chartspaces.chart.left;
1644
1584
  m_chartspaces.lowerChart.right = m_chartspaces.chart.right;
1645
- m_chartspaces.lowerChart.bottom = m_canvas.height - parseInt(m_chartCss['margin-bottom']);
1585
+ m_chartspaces.lowerChart.bottom = m_canvas.height - m_chartCss.marginBottom;
1646
1586
  m_chartspaces.lowerChart.width = m_canvas.width;
1647
1587
  }
1648
1588
 
@@ -1658,7 +1598,6 @@ function Milli_Chart(settings) {
1658
1598
  }
1659
1599
  m_lastDrawnInstrument = _this.instruments[0].insref;
1660
1600
  if (m_ctx == null) return;
1661
- //console.clear();
1662
1601
  m_datapoints = [];
1663
1602
  if (m_dataPoints.map) m_dataPoints.map.clear();
1664
1603
  m_dataPoints.map = new Map();
@@ -1672,13 +1611,12 @@ function Milli_Chart(settings) {
1672
1611
  var period = _this.settings.chartlen.substring(_this.settings.chartlen.length - 1);
1673
1612
  var len = parseInt(_this.settings.chartlen.substring(0, _this.settings.chartlen.length - 1));
1674
1613
  m_ctx.clearRect(0, 0, m_canvas.width, m_canvas.height);
1675
- m_ctx.fillStyle = m_chartCss['background-color'];
1614
+ m_ctx.fillStyle = m_chartCss.backgroundColor;
1676
1615
  m_ctx.fillRect(0, 0, m_canvas.width, m_canvas.height);
1677
1616
  m_ctx.lineWidth = 1;
1678
1617
  m_ctx.textBaseline = 'top'; // important!
1679
1618
  var i;
1680
1619
  if (period == 'd' && _this.instruments[0].trades.length != 0 && _this.settings.chartlen != 'ytd') {
1681
- _this.settings.graphvalue = 'price'; // om man får nav kanske man skall ta det från datan?
1682
1620
  if (m_zoom.mousedown.timestamp) {
1683
1621
  _this.scaleinfoX.endTimeStamp = m_zoom.mouseup.timestamp > m_zoom.mousedown.timestamp ? m_zoom.mouseup.timestamp : m_zoom.mousedown.timestamp;
1684
1622
  _this.scaleinfoX.startTimeStamp = m_zoom.mouseup.timestamp < m_zoom.mousedown.timestamp ? m_zoom.mouseup.timestamp : m_zoom.mousedown.timestamp;
@@ -1720,6 +1658,7 @@ function Milli_Chart(settings) {
1720
1658
  _this.scaleinfoY.type = 'trades';
1721
1659
  if (_this.instruments.length > 1) {
1722
1660
  // calc factors
1661
+ var instrumentprice;
1723
1662
  for (i = 0; i < _this.instruments[0].trades.length; i++) {
1724
1663
  if (_this.instruments[0].trades[i].timestamp >= _this.scaleinfoX.startTimeStamp) {
1725
1664
  instrumentprice = _this.instruments[0].trades[i].price;
@@ -1761,7 +1700,6 @@ function Milli_Chart(settings) {
1761
1700
  _this.scaleinfoX.endTimeStamp = new Date(_this.scaleinfoX.endTimeStamp.toISOString().substring(0, 10) + 'T' + '00:00:00Z').getTime();
1762
1701
  }
1763
1702
  setTimeSpanData();
1764
- _this.settings.graphvalue = 'price';
1765
1703
  _this.scaleinfoY.type = 'history';
1766
1704
  calcCompareFactors('history');
1767
1705
  _this.instruments[0].factor = 1;
@@ -1785,7 +1723,6 @@ function Milli_Chart(settings) {
1785
1723
  var startdate;
1786
1724
  if (_this.settings.chartlen == 'max' && _this.instruments[0].history.length > 1) {
1787
1725
  startdate = _this.instruments[0].history[0].timestamp;
1788
- //console.log('max', new Date(startdate));
1789
1726
  } else
1790
1727
  if (_this.settings.chartlen == 'ytd') {
1791
1728
  startdate = new Date(new Date().getFullYear() - 1 + '-12-30').getTime(); // TODO, hur skall vi göra här om det inte finns data runt här?
@@ -1800,7 +1737,6 @@ function Milli_Chart(settings) {
1800
1737
  }
1801
1738
  setTimeSpanData();
1802
1739
  _this.scaleinfoY.type = 'history';
1803
- _this.settings.graphvalue = 'price';
1804
1740
  calcCompareFactors('history');
1805
1741
 
1806
1742
  _this.instruments[0].factor = 1;
@@ -1819,30 +1755,24 @@ function Milli_Chart(settings) {
1819
1755
  drawYAxisLower();
1820
1756
  drawBoxShadow(m_chartspaces.lowerChart);
1821
1757
  }
1822
- onMouseOut();
1758
+ //onMouseOut();
1823
1759
  };
1824
1760
 
1825
1761
  function drawBoxShadow(space) {
1826
- if (typeof m_chartCss.boxShadow === 'undefined') return;
1827
- var boxShadow = m_chartCss.boxShadow;
1828
- if (boxShadow.indexOf(')') != -1) {
1829
- boxShadow = boxShadow.substring(boxShadow.indexOf(')') + 2);
1830
- }
1831
- var boxshadow = boxShadow.split(' ');
1762
+ if (typeof m_chartCss.boxShadow === 'undefined' || typeof m_chartCss.boxShadow.color === 'undefined') return;
1832
1763
  m_ctx.save();
1833
1764
  m_ctx.beginPath();
1834
- if (parseInt(boxshadow[0]) > 0) {
1835
- m_ctx.strokeStyle = m_chartCss['border-top-color'];
1836
- m_ctx.lineWidth = parseInt(boxshadow[1]);
1837
- m_ctx.moveTo(space.left, space.top);
1838
- m_ctx.lineTo(space.right, space.top);
1765
+ m_ctx.strokeStyle = m_chartCss.boxShadow.color;
1766
+ if (typeof m_chartCss.boxShadow.topWidth !== 'undefined' && m_chartCss.boxShadow.topWidth > 0) {
1767
+ m_ctx.lineWidth = m_chartCss.boxShadow.topWidth;
1768
+ m_ctx.moveTo(space.left + 0.5, space.top + 0.5);
1769
+ m_ctx.lineTo(space.right + 0.5, space.top + 0.5);
1839
1770
  m_ctx.stroke();
1840
1771
  }
1841
- if (parseInt(boxshadow[1]) > 0) {
1842
- m_ctx.strokeStyle = m_chartCss['border-right-color'];
1843
- m_ctx.lineWidth = parseInt(boxshadow[1]);
1844
- m_ctx.moveTo(space.right, space.top + 0.5);
1845
- m_ctx.lineTo(space.right, space.bottom);
1772
+ if (typeof m_chartCss.boxShadow.rightWidth !== 'undefined' && m_chartCss.boxShadow.rightWidth > 0) {
1773
+ m_ctx.lineWidth = m_chartCss.boxShadow.rightWidth;
1774
+ m_ctx.moveTo(space.right + 0.5, space.top + 0.5);
1775
+ m_ctx.lineTo(space.right + 0.5, space.bottom + 0.5);
1846
1776
  m_ctx.stroke();
1847
1777
  }
1848
1778
  m_ctx.closePath();
@@ -1854,8 +1784,11 @@ function Milli_Chart(settings) {
1854
1784
  return item.insref == data.insref;
1855
1785
  });
1856
1786
  if (instr == null) return;
1857
- var last = 0;
1787
+ /*var last = 0;*/
1858
1788
  if (typeof data.name !== 'undefined') instr.name = data.name;
1789
+ if (typeof data.symbol !== 'undefined') instr.symbol = data.symbol;
1790
+ if (typeof data.ticksize !== 'undefined') _this.settings.num_decimals = data.ticksize;
1791
+
1859
1792
  if (typeof data.tradecurrency !== 'undefined') instr.tradecurrency = data.tradecurrency;
1860
1793
  if (data.marketopen && data.marketclose) {
1861
1794
  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
@@ -1896,8 +1829,8 @@ function Milli_Chart(settings) {
1896
1829
  item = [];
1897
1830
  item.timestamp = data.trades[i].timestamp - (data.trades[i].timestamp % 60000);
1898
1831
 
1899
- if (last > item.timestamp) //console.log('ERROR', item.timestamp);
1900
- last = item.timestamp;
1832
+ /*if (last > item.timestamp)
1833
+ last = item.timestamp;*/
1901
1834
  if (typeof data.trades[i].tradeprice !== 'undefined') item.price = parseFloat(data.trades[i].tradeprice) * factor;
1902
1835
  if (typeof data.trades[i].tradequantity !== 'undefined' && data.trades[i].tradequantity != null) {
1903
1836
  item.quantity = parseInt(data.trades[i].tradequantity);
@@ -1949,8 +1882,6 @@ function Milli_Chart(settings) {
1949
1882
  _this.drawChart();
1950
1883
  return;
1951
1884
  }
1952
- /*if (m_modules.quantity == null)
1953
- m_modules.quantity = new MilliChart_Quantity(_this, m_canvas);*/
1954
1885
  _this.drawChart();
1955
1886
  };
1956
1887
 
@@ -2029,9 +1960,9 @@ function Milli_Chart(settings) {
2029
1960
  // TODO: här blir det fel när det är från 00:00: 23:59 men göms av tmpx < startpoint.x
2030
1961
 
2031
1962
  }
2032
- //startpoint.y = Math.round(m_canvas.height - parseInt(m_chartCss['margin-bottom']) - (((data[i].price * factor) - _this.scaleinfoY.minValue) * _this.scaleinfoY.valuePerPixel)) + 0.5;
2033
- startpoint.y = Math.round(m_chartspaces.chart.height - parseInt(m_chartCss['margin-bottom']) - (((data[i].price * factor) - _this.scaleinfoY.minValue) * _this.scaleinfoY.valuePerPixel)) + 0.5;
2034
- var maxy = maxy > startpoint.y ? maxy : startpoint.y;
1963
+ //startpoint.y = Math.round(m_canvas.height - m_chartCss.marginBottom - (((data[i].price * factor) - _this.scaleinfoY.minValue) * _this.scaleinfoY.valuePerPixel)) + 0.5;
1964
+ startpoint.y = Math.round(m_chartspaces.chart.height - m_chartCss.marginBottom - (((data[i].price * factor) - _this.scaleinfoY.minValue) * _this.scaleinfoY.valuePerPixel)) + 0.5;
1965
+ maxy = maxy > startpoint.y ? maxy : startpoint.y;
2035
1966
 
2036
1967
  startpoint.x = Math.round(m_chartspaces.chart.left + ((data[i].timestamp - _this.scaleinfoX.startDate.getTime()) / _this.scaleinfoX.timePerPixel)) + 0.5;
2037
1968
  startpoint.x -= offset;
@@ -2046,7 +1977,6 @@ function Milli_Chart(settings) {
2046
1977
  }
2047
1978
 
2048
1979
  function plotData(data, instrument) {
2049
- //console.log('plotting',instrument,_this.instruments[instrument],_this.instruments);
2050
1980
  m_ctx.save();
2051
1981
  m_ctx.strokeStyle = m_instrumentCss[instrument].color;
2052
1982
  var factor = _this.instruments[instrument].factor;
@@ -2054,7 +1984,7 @@ function Milli_Chart(settings) {
2054
1984
  var endpoint = { x: 0, y: 0 };
2055
1985
  var startDate = _this.scaleinfoX.startTimeStamp;
2056
1986
  var len = data.length;
2057
- m_ctx.lineWidth = parseInt(m_instrumentCss[instrument].width);
1987
+ m_ctx.lineWidth = m_instrumentCss[instrument].width;
2058
1988
  m_ctx.beginPath();
2059
1989
 
2060
1990
  var startx = 0;
@@ -2064,6 +1994,7 @@ function Milli_Chart(settings) {
2064
1994
  var addedcloseprice1d = false;
2065
1995
  var maxy = 0;
2066
1996
  var hCurveLastPoint = null;
1997
+ var quantity = 0;
2067
1998
  for (var i = 0; i < len; i++) {
2068
1999
  var currentDate;
2069
2000
  var lastItem = data[i];
@@ -2074,7 +2005,6 @@ function Milli_Chart(settings) {
2074
2005
  continue;
2075
2006
  }
2076
2007
  if (data[i].timestamp > _this.scaleinfoX.endTimeStamp) {
2077
- //console.log('break', data[i].timestamp, _this.scaleinfoX.endTimeStamp);
2078
2008
  break; // continue?
2079
2009
  }
2080
2010
 
@@ -2083,11 +2013,11 @@ function Milli_Chart(settings) {
2083
2013
  continue;
2084
2014
  }
2085
2015
  var endtimeToday = new Date(data[i].timestamp);
2016
+ 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
2086
2017
  if (_this.scaleinfoY.type != 'history') {
2087
2018
  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
2088
2019
  }
2089
2020
  if (data[i].timestamp > endtimeToday.getTime()) {
2090
- console.log('no plot');
2091
2021
  continue; // dataticks efter stängning ritas inte
2092
2022
  }
2093
2023
 
@@ -2095,32 +2025,15 @@ function Milli_Chart(settings) {
2095
2025
  //var point = { price: data[i].price, open: null, x: endpoint.x - 0.5, y: endpoint.y - 0.5, timestamp: data[i].timestamp };
2096
2026
  //m_datapoints.push(point);
2097
2027
  } else
2098
- if (addedcloseprice1d == false && m_zoom.mouseup.timestamp == null) {
2028
+ if (addedcloseprice1d == false && m_zoom.mouseup.timestamp == null && (_this.settings.chartlen == '1d' || _this.settings.chartlen == '0d')) { // only draw closeprice1d on today charts
2099
2029
  currentDate = new Date(data[i].timestamp);
2100
2030
  offset = ((86400000 - _this.scaleinfoX.milliPerDay) / _this.scaleinfoX.timePerPixel) * dateDiffInDays(new Date(startDate), currentDate);
2101
2031
  tmp = new Date(currentDate.toISOString().substring(0, 10) + 'T' + _this.instruments[0].marketopen + 'Z');
2102
2032
  endpoint.x = Math.round(m_chartspaces.chart.left + ((tmp.getTime() - startDate) / _this.scaleinfoX.timePerPixel)) + 0.5 - offset;
2103
2033
  if (_this.settings.chartlen == '1d' || _this.settings.chartlen == '0d') { // plot the closeprice1d
2104
- //endpoint.y = Math.round(m_canvas.height - parseInt(m_chartCss['margin-bottom']) - (((parseFloat(_this.instruments[instrument].closeprice1d) * factor) - _this.scaleinfoY.minValue) * _this.scaleinfoY.valuePerPixel)) + 0.5;
2105
- endpoint.y = Math.round(m_chartspaces.chart.height - parseInt(m_chartCss['margin-bottom']) - (((parseFloat(_this.instruments[instrument].closeprice1d) * factor) - _this.scaleinfoY.minValue) * _this.scaleinfoY.valuePerPixel)) + 0.5;
2034
+ endpoint.y = Math.round(m_chartspaces.chart.height - m_chartCss.marginBottom - (((parseFloat(_this.instruments[instrument].closeprice1d) * factor) - _this.scaleinfoY.minValue) * _this.scaleinfoY.valuePerPixel)) + 0.5;
2106
2035
  } else {
2107
- //endpoint.y = Math.round(m_canvas.height - parseInt(m_chartCss['margin-bottom']) - (((parseFloat(lastItem.price) * factor) - _this.scaleinfoY.minValue) * _this.scaleinfoY.valuePerPixel)) + 0.5;
2108
- endpoint.y = Math.round(m_chartspaces.chart.height - parseInt(m_chartCss['margin-bottom']) - (((parseFloat(lastItem.price) * factor) - _this.scaleinfoY.minValue) * _this.scaleinfoY.valuePerPixel)) + 0.5;
2109
- // do not add closeprice to hover array
2110
- /*
2111
- var x = Math.round(endpoint.x);
2112
- if (!m_dataPoints.arr.includes(x)) {
2113
- m_dataPoints.arr.push(x);
2114
- }
2115
- var obj = m_dataPoints.map.get(x);
2116
- if (obj == null) {
2117
- obj = {};
2118
- obj.timestamp = data[i].timestamp;
2119
- obj.instruments = [];
2120
- m_dataPoints.map.set(x, obj);
2121
- }
2122
- obj.instruments[instrument] = { price: data[i].price, open: data[i].openprice, x: startpoint.x - 0.5, y: startpoint.y - 0.5, timestamp: data[i].timestamp, date: new Date(data[i].timestamp), insref: _this.instruments[instrument].insref, diff: data[i].diff };
2123
- */
2036
+ endpoint.y = Math.round(m_chartspaces.chart.height - m_chartCss.marginBottom - (((parseFloat(lastItem.price) * factor) - _this.scaleinfoY.minValue) * _this.scaleinfoY.valuePerPixel)) + 0.5;
2124
2037
  }
2125
2038
  m_ctx.moveTo(endpoint.x, endpoint.y);
2126
2039
  lastdate = new Date(data[i].timestamp);
@@ -2132,7 +2045,6 @@ function Milli_Chart(settings) {
2132
2045
  currentDate.setHours(lastdate.getHours());
2133
2046
  currentDate.setMinutes(lastdate.getMinutes());
2134
2047
  currentDate.setSeconds(lastdate.getSeconds());
2135
-
2136
2048
  if (lastdate.toISOString().substring(0, 10) != currentDate.toISOString().substring(0, 10)) { // new date
2137
2049
  tmp = new Date(lastdate.toISOString().substring(0, 10) + 'T' + _this.instruments[0].marketclose + 'Z');
2138
2050
  // draw Day separator?
@@ -2159,12 +2071,13 @@ function Milli_Chart(settings) {
2159
2071
  }
2160
2072
  //m_ctx.lineTo(startpoint.x, startpoint.y);
2161
2073
  }
2162
- //startpoint.y = Math.round(m_canvas.height - parseInt(m_chartCss['margin-bottom']) - (((data[i].price * factor) - _this.scaleinfoY.minValue) * _this.scaleinfoY.valuePerPixel)) + 0.5;
2163
- startpoint.y = Math.round(m_chartspaces.chart.height - parseInt(m_chartCss['margin-bottom']) - (((data[i].price * factor) - _this.scaleinfoY.minValue) * _this.scaleinfoY.valuePerPixel)) + 0.5;
2074
+ //startpoint.y = Math.round(m_canvas.height - m_chartCss.marginBottom - (((data[i].price * factor) - _this.scaleinfoY.minValue) * _this.scaleinfoY.valuePerPixel)) + 0.5;
2075
+ startpoint.y = Math.round(m_chartspaces.chart.height - m_chartCss.marginBottom - (((data[i].price * factor) - _this.scaleinfoY.minValue) * _this.scaleinfoY.valuePerPixel)) + 0.5;
2164
2076
  maxy = maxy > startpoint.y ? maxy : startpoint.y;
2165
2077
 
2166
2078
  startpoint.x = Math.round(m_chartspaces.chart.left + ((data[i].timestamp - _this.scaleinfoX.startDate.getTime()) / _this.scaleinfoX.timePerPixel)) + 0.5;
2167
2079
  startpoint.x -= offset;
2080
+ quantity += data[i].quantity;
2168
2081
  if (startpoint.x != endpoint.x || startpoint.y != endpoint.y) {
2169
2082
  var x = Math.round(startpoint.x);
2170
2083
  if (!m_dataPoints.arr.includes(x)) {
@@ -2175,7 +2088,6 @@ function Milli_Chart(settings) {
2175
2088
  obj = {};
2176
2089
  obj.timestamp = data[i].timestamp;
2177
2090
  obj.instruments = [];
2178
- //m_dataPoints.map.set(data[i].timestamp,obj);
2179
2091
  m_dataPoints.map.set(x, obj);
2180
2092
  }
2181
2093
  obj.instruments[instrument] = { price: data[i].price, open: data[i].openprice, x: startpoint.x - 0.5, y: startpoint.y - 0.5, timestamp: data[i].timestamp, date: new Date(data[i].timestamp), insref: _this.instruments[instrument].insref, diff: data[i].diff };
@@ -2187,36 +2099,38 @@ function Milli_Chart(settings) {
2187
2099
  //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"
2188
2100
 
2189
2101
  if (instrument == 0) {
2190
- point = { price: data[i].price, open: data[i].openprice, x: startpoint.x - 0.5, y: startpoint.y - 0.5, timestamp: data[i].timestamp, date: new Date(data[i].timestamp), quantity: data[i].quantity };
2102
+ point = { price: data[i].price, open: data[i].openprice, x: startpoint.x - 0.5, y: startpoint.y - 0.5, timestamp: data[i].timestamp, date: new Date(data[i].timestamp), quantity: quantity };
2191
2103
  if (typeof data[i].dividend !== 'undefined') point.dividend = data[i].dividend;
2192
2104
  if (typeof data[i].diff !== 'undefined') point.diff = data[i].diff;
2105
+ point.quantity = quantity;
2193
2106
  m_datapoints.push(point);
2107
+ quantity = 0;
2194
2108
  }
2195
2109
  }
2196
2110
  } else {
2197
2111
  if (instrument == 0) {
2198
- point = { price: data[i].price, open: data[i].openprice, x: startpoint.x - 0.5, y: startpoint.y - 0.5, timestamp: data[i].timestamp, date: new Date(data[i].timestamp), insref: _this.instruments[instrument].insref, diff: data[i].diff };
2199
- // if (typeof data[i].diff !== 'undefined') point.diff = data[i].diff
2112
+ point = { price: data[i].price, open: data[i].openprice, x: startpoint.x - 0.5, y: startpoint.y - 0.5, timestamp: data[i].timestamp, date: new Date(data[i].timestamp), insref: _this.instruments[instrument].insref, diff: data[i].diff, quantity: quantity };
2200
2113
  m_datapoints.push(point);
2201
2114
  if (_this.settings.hcurve && _this.scaleinfoY.type == 'history') {
2202
2115
  if (isToday(currentDate)) {
2203
2116
  // only 1 point in hcurve chart, draw line from start of chart to end date
2204
2117
  m_ctx.moveTo(m_chartspaces.chart.left, startpoint.y);
2205
2118
  m_ctx.lineTo(startpoint.x, startpoint.y);
2206
- point = { price: data[i].price, open: data[i].openprice, x: m_chartspaces.chart.left - 0.5, y: startpoint.y - 0.5, timestamp: data[i].timestamp, date: new Date(data[i].timestamp), insref: _this.instruments[instrument].insref, diff: data[i].diff };
2119
+ point = { price: data[i].price, open: data[i].openprice, x: m_chartspaces.chart.left - 0.5, y: startpoint.y - 0.5, timestamp: data[i].timestamp, date: new Date(data[i].timestamp), insref: _this.instruments[instrument].insref, diff: data[i].diff, quantity: quantity };
2207
2120
  m_datapoints.push(point);
2208
- point = { price: data[i].price, open: data[i].openprice, x: startpoint.x - 0.5, y: startpoint.y - 0.5, timestamp: data[i].timestamp, date: new Date(data[i].timestamp), insref: _this.instruments[instrument].insref, diff: data[i].diff };
2121
+ point = { price: data[i].price, open: data[i].openprice, x: startpoint.x - 0.5, y: startpoint.y - 0.5, timestamp: data[i].timestamp, date: new Date(data[i].timestamp), insref: _this.instruments[instrument].insref, diff: data[i].diff, quantity: quantity };
2209
2122
  m_datapoints.push(point);
2210
2123
  startx = m_chartspaces.chart.left;
2211
2124
  starty = startpoint.y;
2212
2125
  // last point so break out and store startx and starty from fake point
2213
2126
  break;
2214
2127
  } else if (hCurveLastPoint) {
2215
- /* var y = Math.round(m_canvas.height - parseInt(m_chartCss['margin-bottom']) - (((hCurveLastPoint.price * factor) - _this.scaleinfoY.minValue) * _this.scaleinfoY.valuePerPixel)) + 0.5;
2128
+ /* var y = Math.round(m_canvas.height - m_chartCss.marginBottom - (((hCurveLastPoint.price * factor) - _this.scaleinfoY.minValue) * _this.scaleinfoY.valuePerPixel)) + 0.5;
2216
2129
  m_ctx.moveTo(m_chartspaces.chart.left, y);
2217
2130
  m_ctx.lineTo(startpoint.x, y);*/
2218
2131
  }
2219
2132
  }
2133
+ quantity = 0;
2220
2134
  }
2221
2135
  m_ctx.moveTo(startpoint.x, startpoint.y);
2222
2136
  startx = startpoint.x;
@@ -2234,49 +2148,28 @@ function Milli_Chart(settings) {
2234
2148
  });
2235
2149
  m_ctx.stroke();
2236
2150
  if (_this.settings.fillchart == true && instrument == 0) {
2237
- // m_ctx.lineTo(startpoint.x, m_canvas.height - parseInt(m_chartCss['margin-bottom']) + 0.5);
2238
- // m_ctx.lineTo(startx, m_canvas.height - parseInt(m_chartCss['margin-bottom']) + 0.5);
2239
- m_ctx.lineTo(startpoint.x, m_chartspaces.chart.height - parseInt(m_chartCss['margin-bottom']) + 0.5);
2240
- m_ctx.lineTo(startx, m_chartspaces.chart.height - parseInt(m_chartCss['margin-bottom']) + 0.5);
2151
+ m_ctx.lineTo(startpoint.x, m_chartspaces.chart.height - m_chartCss.marginBottom + 0.5);
2152
+ m_ctx.lineTo(startx, m_chartspaces.chart.height - m_chartCss.marginBottom + 0.5);
2241
2153
  m_ctx.lineTo(startx, starty);
2242
2154
  m_ctx.closePath();
2243
- if (true == m_instrumentCss[0]['background-image'].startsWith('linear-gradient')) {
2244
- var colors = m_instrumentCss[0]['background-image'].substring(m_instrumentCss[0]['background-image'].indexOf('(') + 1);
2245
- var col0; // = 'rgba(0,200,0,1)';
2246
- var col1; // = 'rgba(0,200,0,0)';
2247
- if (typeof colors === 'string') {
2248
- col0 = colors.substring(0, colors.lastIndexOf('rgba'));
2249
- col0 = col0.substring(0, col0.lastIndexOf(','));
2250
- col1 = colors.substring(colors.lastIndexOf('rgba'), colors.lastIndexOf(')'));
2251
- }
2252
- var grd = m_ctx.createLinearGradient(0, 0, 0, m_chartspaces.chart.height - m_chartspaces.chart.top - parseInt(m_chartCss['margin-bottom']));
2253
- grd.addColorStop(0, col0);
2254
- grd.addColorStop(1, col1);
2155
+ if (typeof m_instrumentCss[0].backgroundLinearGradient !== 'undefined' && typeof m_instrumentCss[0].backgroundLinearGradient.topColor !== 'undefined' && typeof m_instrumentCss[0].backgroundLinearGradient.bottomColor !== 'undefined') {
2156
+ var grd = m_ctx.createLinearGradient(0, 0, 0, m_chartspaces.chart.height - m_chartspaces.chart.top - m_chartCss.marginBottom);
2157
+ grd.addColorStop(0, m_instrumentCss[0].backgroundLinearGradient.topColor);
2158
+ grd.addColorStop(1, m_instrumentCss[0].backgroundLinearGradient.bottomColor);
2255
2159
  m_ctx.fillStyle = grd;
2256
2160
  } else {
2257
- m_ctx.fillStyle = m_instrumentCss[0]['background-image'];
2161
+ if (typeof m_instrumentCss[0].backgroundColor !== 'undefined')
2162
+ m_ctx.fillStyle = m_instrumentCss[0].backgroundColor;
2258
2163
  }
2259
2164
  m_ctx.fill();
2260
2165
  } else
2261
2166
  m_ctx.closePath();
2262
- // eftersom vi kör med m_datapoints här så missar vi dom som plottas på samma ställe som punkten innan
2167
+ // 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???
2263
2168
  plotExternalHistoricalData(data);
2264
- /*for (var i = 0; i < m_datapoints.length; i++) {
2265
- if (m_datapoints[i].dividend) {
2266
- console.log(m_datapoints[i]);
2267
- m_ctx.beginPath();
2268
- m_ctx.arc(m_datapoints[i].x, m_datapoints[i].y - 20, 10, 0, 2 * Math.PI, false);
2269
- m_ctx.fillStyle = 'green';
2270
- m_ctx.fill();
2271
- m_ctx.stroke()
2272
- }
2273
- }*/
2274
-
2275
2169
  m_ctx.restore();
2276
2170
  }
2277
2171
 
2278
2172
  function drawCompare(resp) {
2279
- var factor;
2280
2173
  parseData(resp[0], 1);
2281
2174
  _this.drawChart();
2282
2175
  return;
@@ -2334,11 +2227,11 @@ function Milli_Chart(settings) {
2334
2227
 
2335
2228
  _this.instruments[pos] = instr;
2336
2229
  if (_this.settings.compare1 != '') {
2337
- var url = milli_data_api_url + "widget=intradaychart&token=" + _this.settings.token + "&target=buildwidget&fields=name,tradecurrency,date,time,tradeprice,tradequantity,marketopen,marketclose&language=sv&startdate=" + _this.settings.startdateintraday + "&compress=1&insref=" + instrument + '&intradaylen=' + _this.settings.intradaylen;
2230
+ var url = milli_data_api_url + "widget=intradaychart&token=" + _this.settings.token + "&target=buildwidget&fields=name,tradecurrency,date,time,tradeprice,tradequantity,marketopen,marketclose&language=sv&compress=1&insref=" + instrument + '&intradaylen=' + _this.settings.intradaylen;
2338
2231
  millistream_data_api.fetch(url, function(data) {
2339
2232
  drawCompare(data);
2340
2233
  });
2341
- url = milli_data_api_url + "widget=historychart&token=" + _this.settings.token + "&target=buildwidget&insref=" + instrument + "&fields=name,tradecurrency,date,closeprice,closequantity,marketopen,marketclose&language=sv&startdate=" + _this.settings.startdate + "&compress=1";
2234
+ url = milli_data_api_url + "widget=historychart&token=" + _this.settings.token + "&target=buildwidget&insref=" + instrument + "&fields=name,tradecurrency,date,closeprice,closequantity,marketopen,marketclose&language=sv&startdate=" + _this.settings.startdate + "&adjusted=1";
2342
2235
  millistream_data_api.fetch(url, function(data) {
2343
2236
  drawCompare(data);
2344
2237
  });
@@ -2431,9 +2324,9 @@ function Milli_Chart(settings) {
2431
2324
  _this.drawChart();
2432
2325
 
2433
2326
  if (_this.settings.streaming != false && typeof resp[0].trades !== 'undefined') {
2434
- if (MillistreamWidgetApi_isObjectEmpty(_this.unsubscriptions) == false) {
2327
+ /*if (MillistreamWidgetApi_isObjectEmpty(_this.unsubscriptions) == false) {
2435
2328
  _this.settings.streaming.MillistreamWidgetStreamingApi_unsubscribe(_this);
2436
- }
2329
+ }*/
2437
2330
  m_requestid = _this.settings.streaming.MillistreamWidgetStreamingApi_subscribeInstruments(_this, m_requestid, [_this.settings.instrument]);
2438
2331
  //_this.requestid = _this.settings.streaming.MillistreamWidgetStreamingApi_subscribeInstruments(_this, _this.requestid, m_insrefs);
2439
2332
  }
@@ -2449,7 +2342,7 @@ function Milli_Chart(settings) {
2449
2342
  return;
2450
2343
  }
2451
2344
  if (json['3'] && json['36'] && json['13'] && (json['12'] || json['201'])) {
2452
- var timestamp = new Date(json['3'] + 'T' + json['36'] + 'Z').getTime(); // - m_tz_offset; // tz_offset in minutes
2345
+ var timestamp = new Date(json['3'] + 'T' + json['36'].substring(0, 6) + '00' + 'Z').getTime();
2453
2346
 
2454
2347
  // TODO hash/strangle with YYYY-mm-dd hh:mm:00 trades and only draw once per minute
2455
2348
  var data = instr.hashmap.get(timestamp);
@@ -2460,122 +2353,51 @@ function Milli_Chart(settings) {
2460
2353
  data.timestamp = timestamp;
2461
2354
  instr.hashmap.set(data.timestamp, data);
2462
2355
  data.price = parseFloat(json['12']); // eller 201 för tradeyield
2356
+ data.open = parseFloat(json['12']); // eller 201 för tradeyield
2357
+ data.high = parseFloat(json['12']); // eller 201 för tradeyield
2358
+ data.low = parseFloat(json['12']); // eller 201 för tradeyield
2463
2359
  data.quantity = parseInt(json['13']);
2464
2360
  if (instr.trades.length != 0 && data.timestamp < instr.trades[instr.trades.length - 1].timestamp) {
2465
2361
  //console.log("pushtrade is older than last trade ignoring, should file it on correct postition");
2466
2362
  } else
2467
2363
  instr.trades.push(data);
2468
2364
  } else {
2469
- //console.log(timestamp, 'old trade', data);
2365
+ data.price = parseFloat(json['12']); // eller 201 för tradeyield
2366
+ data.quantity += parseInt(json['13']);
2367
+ update = true;
2470
2368
  // updatera med quantity, open , high,low osv?
2471
2369
  }
2472
2370
  }
2473
- if (update) _this.drawChart();
2371
+ if (update) _this.drawChart(); // hover försvinner... (harris också)
2474
2372
  };
2475
2373
 
2476
- function readCss() {
2477
- //console.log("read css in");
2478
- var test = document.querySelector('.millistream-chart');
2479
- var properties = getComputedStyle(test);
2480
- m_chartCss['background-color'] = properties.backgroundColor;
2481
- m_chartCss['margin-top'] = properties.marginTop;
2482
- m_chartCss['margin-bottom'] = properties.marginBottom;
2483
- m_chartCss['margin-left'] = properties.marginLeft;
2484
- m_chartCss['margin-right'] = properties.marginRight;
2485
- //m_chartCss['box-shadow'] = properties.boxShadow;
2486
- m_chartCss.boxShadow = properties.boxShadow;
2487
- m_chartCss['border-right-color'] = properties.borderRightColor;
2488
- m_chartCss['border-left-color'] = properties.borderLeftColor;
2489
-
2490
- //console.log(properties.marginTop, properties.marginBottom, properties.marginLeft, properties.marginRight);
2491
- var siteURL = new URL(document.URL);
2492
- var cssURL;
2493
- for (var i = 0; i < document.styleSheets.length; i++) {
2494
- if (document.styleSheets[i].href != null)
2495
- cssURL = new URL(document.styleSheets[i].href);
2496
- else cssURL = null;
2497
- // console.log(document.styleSheets,cssURL);
2498
- // if(typeof document.styleSheets[i].host ==='undefined' ) continue;
2499
- if (cssURL != null && siteURL.host != cssURL.host) continue; // cssURL can be null on localhost
2500
- if (typeof document.styleSheets[i] === 'undefined') continue;
2501
- var yLeg = false;
2502
- for (var s = 0; s < document.styleSheets[i].cssRules.length; s++) {
2503
- // console.log(document.styleSheets[i].cssRules[s]);
2504
- if (typeof document.styleSheets[i].cssRules[s].selectorText !== 'undefined') {
2505
- var rules = document.styleSheets[i].cssRules[s].selectorText.split(',');
2506
- for (var ss = 0; ss < rules.length; ss++) {
2507
- // console.log(rules[ss]);
2508
- var ref = null;
2509
- rules[ss] = rules[ss].split(' ').join('');
2510
- switch (rules[ss]) {
2511
- case '.millistream-chart-x-legend':
2512
- ref = m_xLegendCss;
2513
- break;
2514
- case '.millistream-chart-y-legend':
2515
- yLeg = true;
2516
- ref = m_yLegendCss;
2517
- break;
2518
- case '.millistream-chart-y2-legend':
2519
- ref = m_y2LegendCss;
2520
- break;
2521
- case '.millistream-chart-legend':
2522
- // ref = m_LegendCss;
2523
- break;
2524
- case '.millistream-chart':
2525
- //ref = m_chartCss;
2526
- break;
2527
- case '.millistream-chart-horizontal-grid':
2528
- ref = m_gridHorizontalCss;
2529
- break;
2530
- case '.millistream-chart-vertical-grid':
2531
- ref = m_gridVerticalCss;
2532
- break;
2533
- case '.millistream-chart-instrument':
2534
- //console.log('chart');
2535
- ref = m_instrumentCss[0];
2536
- break;
2537
- case '.millistream-chart-compare1':
2538
- ref = m_instrumentCss[1];
2539
- break;
2540
- case '.millistream-chart-compare2':
2541
- ref = m_instrumentCss[2];
2542
- break;
2543
- case '.millistream-chart-compare3':
2544
- ref = m_instrumentCss[3];
2545
- break;
2546
- }
2547
- //console.log(ref);
2548
- if (ref != null) {
2549
- for (var r = 0; r < document.styleSheets[i].cssRules[s].style.length; r++) {
2550
- ref[document.styleSheets[i].cssRules[s].style[r]] = document.styleSheets[i].cssRules[s].style[document.styleSheets[i].cssRules[s].style[r]];
2551
- }
2552
- }
2553
- }
2554
- }
2555
- }
2556
- }
2557
- //console.log("read css out");
2558
-
2559
- }
2560
-
2561
2374
  function changeOrientation() {
2562
2375
  if (m_canvas == null) return;
2563
- console.log('resize');
2564
2376
  // set size 0 so target div does not expand due to chartsize
2565
- readCss();
2566
- //m_canvas.setAttribute('height', '0');
2567
- //m_canvas.setAttribute('width', '0');
2377
+ //readCss(); // TODO
2568
2378
 
2569
2379
  m_canvas.setAttribute('height', _this.settings.target.getBoundingClientRect().height);
2570
- m_canvas.setAttribute('width', _this.settings.target.getBoundingClientRect().width); // läs från css?
2571
- //m_canvas.setAttribute('height', _this.settings.target.offsetHeight);
2572
- //m_canvas.setAttribute('width', _this.settings.target.offsetWidth); // läs från css?
2380
+ m_canvas.setAttribute('width', _this.settings.target.getBoundingClientRect().width);
2573
2381
  _this.drawChart();
2574
2382
  }
2575
2383
 
2384
+ function getXhrJson(url) {
2385
+ var req = new XMLHttpRequest();
2386
+ req.onload = function() {
2387
+ _this.buildwidget(JSON.parse(this.responseText));
2388
+ }
2389
+ req.open("GET", url, true);
2390
+ req.onerror = function(error) {
2391
+ console.log('Fetch data error', error);
2392
+ }
2393
+ req.send();
2394
+ }
2395
+
2576
2396
  this.drawWidget = function() {
2577
2397
  // remove standard fields from array, they will be requested anyway
2578
- _this.settings.fields = _this.settings.fields.filter(function(obj) { return ['name', 'tradecurrency', 'time', 'date', 'tradeprice', 'tradequantity', 'marketopen', 'marketclose', 'closeprice1d', 'closeprice', 'closequantity'].indexOf(obj) == -1 });
2398
+ _this.settings.fields = _this.settings.fields.filter(function(obj) {
2399
+ return ['name', 'tradecurrency', 'time', 'date', 'tradeprice', 'tradequantity', 'marketopen', 'marketclose', 'closeprice1d', 'closeprice', 'closequantity'].indexOf(obj) == -1;
2400
+ });
2579
2401
  //_this.settings.drawy2axis = false;
2580
2402
  m_tradedates = [];
2581
2403
  _this.settings.scaleinfoY = {};
@@ -2583,8 +2405,6 @@ function Milli_Chart(settings) {
2583
2405
  m_dummyDiv.style.display = 'none';
2584
2406
  m_dummyDiv.setAttribute('class', 'millistream-chart');
2585
2407
  _this.settings.target.appendChild(m_dummyDiv);
2586
- readCss();
2587
- m_tz_offset = new Date().getTimezoneOffset() * 60000;
2588
2408
  _this.instruments = []; // Hmm
2589
2409
  var instr = {
2590
2410
  insref: _this.settings.instrument,
@@ -2594,26 +2414,33 @@ function Milli_Chart(settings) {
2594
2414
  intradayQuantity: []
2595
2415
  };
2596
2416
  _this.instruments.push(instr);
2597
- var d, url;
2417
+ var d, url, oldfields;
2598
2418
  if (_this.settings.intradaylen) {
2599
2419
  d = new Date().getTime();
2600
2420
  var e = new Date();
2601
2421
  var days = 0;
2422
+ var newlen = 0;
2602
2423
  while (days < _this.settings.intradaylen - 1) { // include today
2603
2424
  d -= 86400000;
2604
2425
  e.setTime(d);
2605
2426
  if (e.getDay() != 0 && e.getDay() != 6)
2606
2427
  days++;
2428
+ newlen++;
2607
2429
  }
2608
- var oldfields = _this.settings.fields;
2430
+ _this.settings.intradaylen = newlen.toString();
2431
+ oldfields = _this.settings.fields;
2609
2432
  _this.settings.fields = [...['name', 'tradecurrency', 'time', 'date', 'tradeprice', 'tradequantity', 'marketopen', 'marketclose', 'closeprice1d'], ...oldfields];
2610
2433
  _this.settings.startdate = e.getFullYear() + '-' + zeroPad(e.getMonth() + 1, 2) + '-' + zeroPad(e.getDate(), 2);
2611
- _this.settings.startdateintraday = _this.settings.startdate;
2434
+ //_this.settings.startdateintraday = _this.settings.startdate;
2612
2435
  url = MillistreamWidgetApi_buildQuery(_this, 'intradaychart');
2613
2436
  _this.settings.fields = oldfields;
2614
- millistream_data_api.fetch(url, function(data) {
2615
- _this.buildwidget(data);
2616
- });
2437
+ if (_this.settings.xhr) {
2438
+ getXhrJson(url);
2439
+ } else {
2440
+ millistream_data_api.fetch(url, function(data) {
2441
+ _this.buildwidget(data);
2442
+ });
2443
+ }
2617
2444
  }
2618
2445
  if (_this.settings.historylen) {
2619
2446
  var len = _this.settings.historylen.substring(0, _this.settings.historylen.length - 1);
@@ -2659,22 +2486,24 @@ function Milli_Chart(settings) {
2659
2486
  }
2660
2487
  // must be reset when changing from intraday -> history and vice versa
2661
2488
  startdate = new Date(startdate);
2662
- var oldfields = _this.settings.fields;
2489
+ oldfields = _this.settings.fields;
2663
2490
  _this.settings.fields = [...['name', 'tradecurrency', 'date', 'closeprice', 'closequantity', 'marketopen', 'marketclose'], ...oldfields];
2664
2491
  _this.settings.startdate = startdate.getFullYear() + '-' + zeroPad(startdate.getMonth() + 1, 2) + '-' + zeroPad(startdate.getDate(), 2);
2665
2492
  url = MillistreamWidgetApi_buildQuery(_this, 'historychart');
2666
2493
  _this.settings.fields = oldfields;
2667
- //console.log(_this.settings.fields);
2668
- millistream_data_api.fetch(url, function(data) {
2669
- _this.buildwidget(data);
2494
+ if (_this.settings.xhr) {
2495
+ getXhrJson(url);
2496
+ } else {
2497
+ millistream_data_api.fetch(url, function(data) {
2498
+ _this.buildwidget(data);
2670
2499
 
2671
- });
2500
+ });
2501
+ }
2672
2502
  }
2673
2503
  };
2674
2504
  if (this.settings.autodraw == true) this.drawWidget();
2675
2505
 
2676
2506
  window.addEventListener('resize', function() {
2677
- //console.log('2');
2678
2507
  if (m_canvas != null)
2679
2508
  changeOrientation();
2680
2509
 
@@ -3019,6 +2848,10 @@ function MillistreamWidgetApi_buildQuery(widget, type) {
3019
2848
  if (typeof widget.settings.intradaylen !== 'string' && widget.settings.intradaylen !== null) throw new Error(widget.constructor.name + ': intradaylen is not valid');
3020
2849
  url += '&intradaylen=' + widget.settings.intradaylen;
3021
2850
  }
2851
+ if (typeof widget.settings.xhr !== 'undefined' && widget.settings.xhr == true) {
2852
+ url += '&xhr=1';
2853
+ }
2854
+
3022
2855
  return url;
3023
2856
  }
3024
2857
 
@@ -3711,6 +3544,9 @@ function MillistreamWidgetApi_getColumnInfo(widget, name) {
3711
3544
  case '1022':
3712
3545
  case 'marketcap':
3713
3546
  return [1022, 'numeric', 'right', widget.get_lang_text(name) || name, 12];
3547
+ case '54':
3548
+ case 'marketplace':
3549
+ return [54, 'numeric', 'left', widget.get_lang_text(name) || name, 0];
3714
3550
  case 'marketplacename':
3715
3551
  return [0, 'string', 'left', widget.get_lang_text(name) || name, 0];
3716
3552
  case '119':
@@ -4853,6 +4689,7 @@ var MillistreamWidgetSettings = {
4853
4689
  thousandseparator: ' ',
4854
4690
  streaming: false
4855
4691
  };
4692
+
4856
4693
  function MillistreamWidgetStreamingApi(settings) {
4857
4694
  var _this = this;
4858
4695
  _this.settings = {
@@ -5253,6 +5090,7 @@ function MillistreamWidgetStreamingApi(settings) {
5253
5090
  }
5254
5091
  exports.Milli_Chart = Milli_Chart;
5255
5092
  exports.MillistreamWidgetSettings = MillistreamWidgetSettings;
5093
+ exports.formatDate = formatDate;
5256
5094
  exports.MillistreamWidgetStreamingApi = MillistreamWidgetStreamingApi;
5257
5095
 
5258
5096
  exports.setDataApiUrl = function(url) {