PageSourceSearch

https://companiesmarketcap.com/js/chart1.js?v=41

js companiesmarketcap.com collected 2026-10-01 08:44:03 UTC 21,236 bytes, 610 lines download raw bytes

1class CmcChart {
2
3	debounce(func){
4	  var timer;
5	  return function(event){
6	    if(timer) clearTimeout(timer);
7	    timer = setTimeout(func,100,event);
8	  };
9	}
10
11	formatCoinCap(val) {
12		if(val == 0) {
13			return '0';
14		}
15		if(val >= 1000000000000) {
16			return this.currencySymbol + (Math.round(val/10000000000) / 100) + 'T';
17		}
18
19		if(val >= 100000000) {
20			return this.currencySymbol + (Math.round(val/10000000) / 100) + 'B';
21		}
22
23		if(val < 0) {
24			if(val <= -1000000000000) {
25				return '-' + this.currencySymbol + Math.abs(Math.round(val/10000000000) / 100) + 'T';
26			}
27			if(val <= -100000000) {
28				return '- ' + this.currencySymbol + Math.abs(Math.round(val/10000000) / 100) + 'B';
29			}
30		}
31
32		if(val < 0) {
33			return '-' + this.currencySymbol +  Math.abs(Math.round(val/10000) / 100) + 'M';
34		}
35
36		return this.currencySymbol + (Math.round(val/10000) / 100) + 'M';
37	}
38
39	loadConfig() {
40		if (typeof this.dateFormat == 'undefined') {
41			this.dateFormat = 'dmy';
42		}
43		if (typeof this.currencySymbol == 'undefined') {
44			this.currencySymbol = '$';
45		}
46		this.granularity = 1;
47		this.posX = 0;
48		this.posXMargin = 70;
49		this.posYMargin = 50;
50		this.posXChartMargin = 0;
51		this.height = this.chart.clientHeight - this.posYMargin - 80;
52		this.width = this.chart.clientWidth - this.posXMargin - 5;
53		this.chartMetaData = {};
54		this.comparisonCursorHasBeenSet = false;
55
56		this.months = ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'];
57
58		if(typeof this.buildChartType != 'undefined') {
59			if(this.buildChartType == "line-chart") {
60				this.buildChartContent = this.buildLineChartContent;
61			}
62			if(this.buildChartType == "bar-chart") {
63				this.buildChartContent = this.buildBarChartContent;
64				if(typeof this.zeroLineClass == 'undefined') {
65					this.zeroLineClass = '';
66				}
67
68				this.rectWidth = Math.round(((this.width - this.posXMargin) / 2) / this.data.length);
69				if(this.rectWidth < 1) {
70					this.rectWidth = 1;
71				}
72				this.posXChartMargin = this.rectWidth/2;
73			}
74		} else {
75			this.buildChartContent = this.buildLineChartContent;
76		}
77
78		if(typeof this.zeroLineClass == 'undefined') {
79			this.zeroLineClass = 'zero-line';
80		}
81	}
82
83	/* Build bar chart */
84	buildBarChartContent() {
85		var rectangles = "";
86
87		for(var key in this.data) {
88			var entry = this.data[key];
89			var date;
90			var val;
91			if(typeof entry["d"] == 'undefined') {
92				date = Date.parse(key + "-01-01") / 1000;
93				val = this.data[key];
94			} else {
95				date = entry["d"];
96				if(typeof entry["m"] != 'undefined') {
97					val = entry["m"] * 100000;
98				} else if(typeof entry["v"] != 'undefined') {
99					val = entry["v"];
100				}
101			}
102
103			if(date >= this.dateMin) {
104				this.posX = Math.round(((date - this.dateMin) * (this.width - this.posXChartMargin * 2))/(this.dateMax - this.dateMin)) + this.posXMargin + this.posXChartMargin;
105			}
106			this.posY = this.height - Math.round(((val - this.valMin) * this.height)/(this.valDiff)) + this.posYMargin;
107
108
109			//sparkline = sparkline.concat(this.posX + "," + this.posY);
110			var posYRectStart = this.posY;
111			if(typeof this.zeroLineYpos != 'undefined') {
112				if(this.posY <= this.zeroLineYpos) {
113					var rectHeight = this.zeroLineYpos - this.posY;
114				} else {
115					posYRectStart = this.zeroLineYpos;
116					var rectHeight = this.posY - this.zeroLineYpos;
117				}
118			} else {
119				var rectHeight = (this.posYMargin + this.height) - this.posY;
120			}
121			rectangles = rectangles.concat('<rect class="chart-bar" x="' + (this.posX - this.rectWidth / 2) + '" y="' + posYRectStart + '" width="'+this.rectWidth+'" height="' + rectHeight + '" rx="1" />');
122
123			this.chartMetaData[this.posX] = {"y":this.posY, "d": date, "m" : val};
124			val = val / 100000;
125
126		}
127
128		return rectangles;
129	}
130
131	buildLineChartContent() {
132		var isFirstPass = true;
133		var sparklineFill = "";
134		var sparkline = "";
135
136		for(var key in this.data) {
137			var entry = this.data[key];
138			var date;
139			var val;
140			if(typeof entry["d"] == 'undefined') {
141				date = Date.parse(key + "-01-01") / 1000;
142				val = this.data[key];
143			} else {
144				date = entry["d"];
145				if(typeof entry["m"] != 'undefined') {
146					val = entry["m"] * 100000;
147				} else if(typeof entry["v"] != 'undefined') {
148					val = entry["v"];
149				}
150			}
151
152			if(date >= this.dateMin) {
153				this.posX = Math.round(((date - this.dateMin) * this.width)/(this.dateMax - this.dateMin)) + this.posXMargin;
154			}
155			this.posY = this.height - Math.round(((val - this.valMin) * this.height)/(this.valDiff)) + this.posYMargin;
156
157			if(this.posX == 0) {
158				if(isFirstPass) {
159					sparklineFill = 'M' + (this.posXMargin - 2) + ',' + (this.posYMargin + this.height) + ' ';
160					sparkline = "M";
161				} else {
162					sparkline = "L";
163				}
164
165				sparkline =  sparkline.concat((this.posXMargin - 2) + "," + this.posY);
166				sparklineFill = sparklineFill.concat((this.posXMargin - 2) + "," + this.posY);
167			} else {
168
169				if(isFirstPass) {
170					sparklineFill = 'M' + (this.posXMargin - 2) + ',' + (this.posYMargin + this.height) + ' ';
171					sparkline = "M";
172				} else {
173					sparkline = sparkline.concat(" L");
174					sparklineFill = sparklineFill.concat(" L");
175				}
176				sparkline = sparkline.concat(this.posX + "," + this.posY);
177				sparklineFill = sparklineFill.concat(this.posX + "," + this.posY);
178			}
179
180			this.chartMetaData[this.posX] = {"y":this.posY, "d": date, "m" : val};
181			val = val / 100000;
182
183			isFirstPass = false;
184		}
185
186		sparklineFill = sparklineFill.concat(' H' + (this.width + this.posXMargin + 2) + ' V' + (this.height + this.posYMargin));
187
188		return '<path d="' + sparklineFill +'" class="chart-sparkline-fill" stroke-width="0" />' +
189			'<path d="' + sparkline +'" class="chart-sparkline" fill="none" stroke="orange" stroke-width="2px" />';
190	}
191
192	drawDateLegend() {
193		var dateLegend = "";
194
195		let difference = this.dateMax - this.dateMin;
196    	let totalDays = Math.ceil(difference / (3600 * 24));
197    	console.log('TotalDays: ' + totalDays);
198
199    	if(totalDays > 365) {
200			var yearStart = new Date(this.dateMin*1000).getFullYear();
201			var yearEnd = new Date(this.dateMax*1000).getFullYear();
202			var numberOfYears = yearEnd - yearStart;
203
204			if(numberOfYears <= 8) {
205				this.granularity = 1;
206			} else if (numberOfYears <= 15) {
207				this.granularity = 3;
208			} else if (numberOfYears <= 20) {
209				this.granularity = 4;
210			} else {
211				this.granularity = 5;
212			}
213
214			for(var i = yearStart; i <= yearEnd; i++) {
215				var timestampYear = Date.parse(i + "-01-01") / 1000;
216
217				var linePosX = Math.round(((timestampYear - this.dateMin) * (this.width - this.posXChartMargin * 2))/(this.dateMax - this.dateMin)) + this.posXMargin;
218				if(linePosX > this.posXMargin && linePosX < this.width + this.posXMargin) {
219					if(i % this.granularity == 0) {
220						dateLegend = dateLegend.concat('<text x="' + linePosX + '" y="' + (this.posYMargin + this.height + 30) + '" text-anchor="middle" class="small">' + i + '</text>');
221					}
222				}
223			}
224		} else {
225
226			var months = totalDays / 30;
227			if(months <= 6) {
228				this.granularity = 1;
229			} else if (months <= 12) {
230				this.granularity = 3;
231			} else if (months <= 15) {
232				this.granularity = 4;
233			} else {
234				this.granularity = 5;
235			}
236
237			var currentDateTimeStamp = this.dateMin;
238			var i = 0;
239			while(currentDateTimeStamp < this.dateMax && i < 1000) {
240
241				var currentDate = new Date(currentDateTimeStamp*1000);
242
243				var linePosX = Math.round(((currentDateTimeStamp - this.dateMin) * (this.width - this.posXChartMargin * 2))/(this.dateMax - this.dateMin)) + this.posXMargin;
244
245				if(linePosX > this.posXMargin && linePosX < this.width + this.posXMargin) {
246					if(i % this.granularity == 0) {
247						dateLegend = dateLegend.concat('<text x="' + linePosX + '" y="' + (this.posYMargin + this.height + 30) + '" text-anchor="middle" class="small">' + this.months[currentDate.getMonth()] + ' ' + currentDate.getFullYear() + '</text>');
248					}
249				}
250
251				currentDate.setMonth(currentDate.getMonth() + 1);
252				currentDateTimeStamp = currentDate.getTime() / 1000;
253				i++;
254			}
255		}
256
257		return dateLegend;
258	}
259
260	buildChart() {
261		this.valMax = 0;
262		this.dateMin = undefined;
263		this.dateMax = undefined;
264		this.valMax	= undefined;
265		this.valMin	= undefined;
266		if(typeof this.setValMin != "undefined") {
267			this.valMin	= this.setValMin;
268		}
269		this.loadConfig();
270		this.loadChartPosition();
271
272		if (typeof this.data == undefined || this.data.length == 0) {
273			return;
274		}
275
276		for(var key in this.data) {
277			var entry = this.data[key];
278			var date;
279			var val;
280			if(typeof entry["d"] == 'undefined') {
281				date = Date.parse(key + "-01-01") / 1000;
282				val = this.data[key];
283			} else {
284				date = entry["d"];
285				if(typeof entry["m"] != 'undefined') {
286					val = entry["m"] * 100000;
287				} else if(typeof entry["v"] != 'undefined') {
288					val = entry["v"];
289				}
290			}
291
292			if(val === null) {
293				val = 0;
294			}
295
296			if(typeof this.valMin == "undefined") {
297				this.valMin = parseFloat(val);
298			} else {
299				if(parseFloat(val) < this.valMin) {
300					this.valMin = parseFloat(val);
301				}
302			}
303
304			if(typeof this.valMax == "undefined") {
305				this.valMax = parseFloat(val);
306			} else {
307				if(parseFloat(val) > this.valMax) {
308					this.valMax = parseFloat(val);
309				}
310			}
311
312			if(typeof this.dateMin == "undefined") {
313				this.dateMin = date;
314			} else {
315				if(date < this.dateMin) {
316					this.dateMin = date;
317				}
318			}
319
320			if(typeof this.dateMax == "undefined") {
321				this.dateMax = date;
322			} else {
323				if(date > this.dateMax) {
324					this.dateMax = date;
325				}
326			}
327		}
328
329		// draw date legend
330		var dateLinesForeground = "";
331		var dateLines = "";
332
333		dateLines = dateLines.concat(this.drawDateLegend());
334
335		this.granularity = 0;
336		var i = 1;
337		this.valDiff = this.valMax - this.valMin;
338
339		do {
340			if(this.valDiff <= 6 * i) {
341				this.granularity = 1 * i;
342			} else if (this.valDiff <= 12 * i) {
343				this.granularity = 2 * i;
344			} else if (this.valDiff <= 30 * i) {
345				this.granularity = 5 * i;
346			}
347
348			i = i * 10;
349		} while(this.granularity == 0);
350		this.valMax = this.valMax + this.granularity - (this.valMax % this.granularity);
351
352		this.valDiff = this.valMax - this.valMin;
353		for(i = this.valMin + (this.granularity - (this.valMin % this.granularity)) - this.granularity; i <= this.valMax; i+= this.granularity) {
354			console.log("valMin:" + this.valMin);
355			console.log("i:" + i);
356			this.posY = this.height - Math.round(((i - this.valMin) * this.height)/(this.valDiff)) + this.posYMargin;
357
358			if(this.posY >= this.posYMargin && this.posY <= this.height + this.posYMargin) {
359				if(i == 0) {
360					dateLinesForeground = dateLinesForeground.concat('<line x1="' + this.posXMargin + '" y1="' + this.posY + '" y2="' + this.posY + '" x2="' + (this.posXMargin + this.width) + '" class="chart-line-horizontal ' + this.zeroLineClass +'" />');
361					dateLinesForeground = dateLinesForeground.concat('<text x="' + (this.posXMargin - 10) + '" y="' + (this.posY + 6) + '" class="small" text-anchor="end">0</text>');
362					this.zeroLineYpos = this.posY;
363				} else {
364					dateLines = dateLines.concat('<rect x="' + this.posXMargin + '" y="' + this.posY + '" width="' + this.width + '" class="chart-line-horizontal" />');
365					dateLines = dateLines.concat('<text x="' + (this.posXMargin - 10) + '" y="' + (this.posY + 6) + '" class="small" text-anchor="end">' + this.formatCursorValue(i) + '</text>');
366				}
367			}
368		}
369
370		var chartContent = this.buildChartContent();
371
372		//dateLines
373		//sparkline
374
375		var svg =
376		  dateLines +
377
378		'<a href="https://companiesmarketcap.com/">' +
379		'<text x="' + Math.round((this.posXMargin + this.width) / 2) + '" y="20" text-anchor="middle" fill="#808080" font-size="20">' +
380			    '</text>' + // Title place holder is here
381		'</a>' +
382			chartContent +
383			dateLinesForeground +
384			'<rect x="-100" y="' + this.posYMargin + 'px" width="1px" height="'+ this.height + 'px" class="chart-cursor-line"></rect>' +
385			'<rect x="-100" y="' + this.posYMargin + 'px" width="1px" height="'+ this.height + 'px" class="chart-comparison-cursor-line"></rect>' +
386
387			'<rect  x="-150" y="'+this.posYMargin+'" width="100px" height="'+this.height+'" class="chart-comparison-overlay-rect"></rect>' +
388
389			'<circle class="cursorCircleShadow" cx="-50" cy="-50" r="8" opacity="0.5" stroke-width="0" fill="orange" />' +
390			'<circle class="cursor-circle" cx="-50" cy="-50" r="5" stroke-width="1" fill="orange" />' +
391			//'<rect class="cursorTextBox" fill="#ccc">' + 
392			'<text font-size="20" class="cursorText" x="0" y="' + (this.posYMargin - 25) + '" text-anchor="middle"></text>' +
393			'<text class="cursorText2" x="0" y="' + (this.posYMargin - 5) + '" text-anchor="middle"></text>' +
394			//'</rect>' +
395
396			'<a href="https://companiesmarketcap.com/">' +
397			    '<text x="' + (this.posXMargin + this.width - 220) + '" y="' + (this.posYMargin + this.height + 60) + '" text-anchor="right" fill="#808080">' +
398			      'companiesmarketcap.com' +
399			    '</text>' +
400			  '</a>';
401
402		this.chart.innerHTML = svg;
403	}
404
405	loadChart(chartElement, chartData) {
406		this.data = chartData;
407		this.chart = chartElement;
408
409		this.loadConfig();
410
411		this.chart.addEventListener('mousemove', this.updateCursorXY.bind(this));
412		this.chart.addEventListener('touchstart', this.updateCursorXY.bind(this));
413	    this.chart.addEventListener('touchmove', this.updateCursorXY.bind(this));
414	    this.chart.addEventListener('touchcancel', this.hideChartCursor.bind(this));
415	    this.chart.addEventListener('touchend', this.hideChartCursor.bind(this));
416
417		if(typeof this.enableComparisonSlider !== "undefined" || this.enableComparisonSlider) {
418			this.chart.addEventListener('pointerdown', this.mousedown.bind(this));
419			this.chart.addEventListener('pointerup', this.mouseup.bind(this));
420		}
421
422		if(typeof this.formatCursorValue == "undefined") {
423			this.formatCursorValue = this.formatCoinCap;
424		}
425		if(typeof this.formatCursorDate == "undefined") {
426			this.formatCursorDate = this.formatCursorDateDefault;
427		}
428
429		this.loadChartPosition();
430		window.addEventListener('scroll', this.loadChartPosition.bind(this));
431		window.addEventListener('resize', this.buildChart.bind(this));
432
433		this.buildChart();
434	}
435
436	loadChartPosition() {
437		this.marketcapchartRect = this.chart.getBoundingClientRect();
438
439		this.chartXStartMarged = this.posXMargin + this.marketcapchartRect.x - 30;
440		this.chartXEndMarged = this.posXMargin + this.width  + this.marketcapchartRect.x + 30;
441
442		this.chartYStartMarged = this.posYMargin + this.marketcapchartRect.y - 5;
443		this.chartYEndMarged = this.posYMargin + this.height + this.marketcapchartRect.y + 5;
444	}
445
446	findNearestKey(needle, target) {
447		var previousK = 0;
448		for (var k in target){
449		    if(Math.abs(k - needle) > Math.abs(previousK - needle)) {
450		    	return previousK;
451		    }
452		    previousK = k;
453		}
454
455		return previousK;
456	}
457
458	hideChartCursor() {
459		this.chart.getElementsByClassName('cursorText')[0].setAttribute('x', -150);
460		this.chart.getElementsByClassName('cursorText2')[0].setAttribute('x', -150);
461		this.chart.getElementsByClassName('cursor-circle')[0].setAttribute('cx', -150);
462		this.chart.getElementsByClassName('cursorCircleShadow')[0].setAttribute('cx', -150);
463		this.chart.getElementsByClassName('chart-cursor-line')[0].setAttribute('x', -150);
464	}
465
466	formatCursorDateDefault(date, dateFormat) {
467		if(dateFormat == 'y') {
468			return date.getFullYear();
469		} else {
470			return date.getDate() + ' ' + this.months[date.getMonth()] + ' ' + date.getFullYear();
471		}
472	}
473
474	mousedown(event) {
475		if (event.pointerType !== 'mouse') {
476			return;
477		}
478
479		if(true) { // todo check if comparison slider is enabled
480
481			var cursorX = event.clientX;
482			var cursorY = event.clientY;
483
484			console.log(event);
485
486			var nearest = this.findNearestKey((cursorX - this.marketcapchartRect.x), this.chartMetaData);
487			this.chart.getElementsByClassName('chart-comparison-cursor-line')[0].setAttribute('x', nearest);
488
489
490			this.comparisonCursorHasBeenSet = true;
491			this.comparisonNearest = nearest;
492		}
493	}
494
495	mouseup(event) {
496		// hide chart-comparison-cursor-line
497		this.chart.getElementsByClassName('chart-comparison-cursor-line')[0].setAttribute('x', -150);
498		this.chart.getElementsByClassName('chart-comparison-overlay-rect')[0].setAttribute('x', -150);
499		this.chart.getElementsByClassName('chart-comparison-overlay-rect')[0].setAttribute('width', 0);
500		this.comparisonCursorHasBeenSet = false;
501
502		this.updateCursorXY(event);
503	}
504
505	updateCursorXY(event) {
506		var cursorX = event.clientX;
507		var cursorY = event.clientY;
508
509		if(typeof cursorX == "undefined" && event.touches[0] != "undefined") {
510			cursorX = event.touches[0].clientX;
511			cursorY = event.touches[0].clientY;
512		}
513
514		console.log("cursor X:" + cursorX);
515
516		if(cursorX > this.chartXStartMarged && cursorX < this.chartXEndMarged && this.chartYStartMarged < cursorY && this.chartYEndMarged > cursorY) {
517			var cursorTextElem = this.chart.getElementsByClassName('cursorText')[0];
518			var cursorText2Elem = this.chart.getElementsByClassName('cursorText2')[0];
519			var cursorTextBox = this.chart.getElementsByClassName('cursorTextBox')[0];
520			var cursorCircle = this.chart.getElementsByClassName('cursor-circle')[0];
521			var cursorCircleShadow = this.chart.getElementsByClassName('cursorCircleShadow')[0];
522
523			var nearest = parseFloat(
524				this.findNearestKey((cursorX - this.marketcapchartRect.x), this.chartMetaData)
525			);
526
527			this.chart.getElementsByClassName('chart-cursor-line')[0].setAttribute('x', nearest);
528			cursorCircle.setAttribute('cx', nearest);
529			cursorCircle.setAttribute('cy', this.chartMetaData[nearest]['y']);
530			cursorCircleShadow.setAttribute('cx', nearest);
531			cursorCircleShadow.setAttribute('cy', this.chartMetaData[nearest]['y']);
532
533
534
535			if(this.comparisonCursorHasBeenSet) {
536				var comparisonPosX = parseInt(this.chart.getElementsByClassName('chart-comparison-cursor-line')[0].getAttribute('x'));
537				if(comparisonPosX > nearest) {
538					this.chart.getElementsByClassName('chart-comparison-overlay-rect')[0].setAttribute('x', nearest);
539					this.chart.getElementsByClassName('chart-comparison-overlay-rect')[0].setAttribute('width', 
540						Math.abs(nearest - comparisonPosX)
541					);
542				} else {
543					this.chart.getElementsByClassName('chart-comparison-overlay-rect')[0].setAttribute('x', comparisonPosX);
544					this.chart.getElementsByClassName('chart-comparison-overlay-rect')[0].setAttribute('width', 
545						Math.abs(nearest - comparisonPosX)
546					);
547				}
548
549			}
550
551
552
553			var date = new Date(this.chartMetaData[nearest]['d'] * 1000);
554
555			if(this.comparisonCursorHasBeenSet) {
556				var comparisonDate = new Date(this.chartMetaData[this.comparisonNearest]['d'] * 1000);
557
558				var percentageClass = "percentage-green";
559				if((this.comparisonNearest < nearest && this.chartMetaData[this.comparisonNearest]['m'] - this.chartMetaData[nearest]['m'] >= 0)
560				|| (this.comparisonNearest > nearest && this.chartMetaData[this.comparisonNearest]['m'] - this.chartMetaData[nearest]['m'] <= 0)) {
561					percentageClass = "percentage-red";
562				}
563
564				// Calculate the percentage difference
565
566				var val1 = this.chartMetaData[this.comparisonNearest]['m'];
567				var val2 = this.chartMetaData[nearest]['m'];
568
569				if(this.comparisonNearest > nearest) {
570					var val2 = this.chartMetaData[this.comparisonNearest]['m'];
571					var val1 = this.chartMetaData[nearest]['m'];
572				}
573
574				var percentChange = val1 !== 0 ? ((val2 - val1) / Math.abs(val1)) * 100 : 0;
575				var percentChangeText = percentChange >= 0 ? "+" + percentChange.toFixed(2) + "%" : percentChange.toFixed(2) + "%";
576
577				if(this.comparisonNearest <= nearest) {
578				
579					cursorText2Elem.textContent = this.formatCursorDate(comparisonDate, this.dateFormat) + " - " + this.formatCursorDate(date, this.dateFormat);
580					cursorTextElem.innerHTML = this.formatCursorValue(this.chartMetaData[this.comparisonNearest]['m']) + " - " + this.formatCursorValue(this.chartMetaData[nearest]['m']) + " <tspan class=\""+percentageClass+"\">(" + percentChangeText + ")</tspan>";
581				} else {
582					cursorText2Elem.textContent = this.formatCursorDate(date, this.dateFormat) + " - " + this.formatCursorDate(comparisonDate, this.dateFormat);
583					cursorTextElem.innerHTML =  this.formatCursorValue(this.chartMetaData[nearest]['m']) + " - " + this.formatCursorValue(this.chartMetaData[this.comparisonNearest]['m']) + " <tspan class=\""+percentageClass+"\">(" + percentChangeText + ")</tspan>";
584				}
585			} else {
586				cursorText2Elem.textContent = this.formatCursorDate(date, this.dateFormat);
587				cursorTextElem.textContent = this.formatCursorValue(this.chartMetaData[nearest]['m']);
588			}
589
590			var w1 = (cursorTextElem.getBBox().width/2);
591			var w2 = (cursorText2Elem.getBBox().width/2);
592
593			if(nearest - w1 < this.posXMargin || nearest - w2 < this.posXMargin) {
594				var biggestWidth = (w1 > w2)? w1 : w2;
595				cursorTextElem.setAttribute('x', this.posXMargin + biggestWidth);
596				cursorText2Elem.setAttribute('x', this.posXMargin + biggestWidth);
597			} else if(nearest + w1 > this.posXMargin + this.width || nearest + w2 > this.posXMargin + this.width) {
598				var biggestWidth = (w1 > w2)? w1 : w2;
599				cursorTextElem.setAttribute('x', this.posXMargin + this.width - biggestWidth);
600				cursorText2Elem.setAttribute('x', this.posXMargin + this.width - biggestWidth);
601			} else {
602				cursorTextElem.setAttribute('x', nearest);
603				cursorText2Elem.setAttribute('x', nearest);
604			}
605		} else {
606			this.hideChartCursor();
607		}
608	}
609
610}

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.