PageSourceSearch

https://tmsscr.edu.bd/assets/js/amcharts/exporting/amexport.js

js tmsscr.edu.bd collected 2026-10-03 00:44:18 UTC 21,448 bytes, 742 lines download raw bytes

1AmCharts.AmExport = AmCharts.Class({
2	construct: function(chart, cfg) {
3		var _this = this;
4		_this.DEBUG = false;
5		_this.chart = chart;
6		_this.canvas = null;
7		_this.svgs = [];
8		_this.userCFG = cfg;
9
10		_this.buttonIcon = 'export.png';
11		_this.exportPNG = true;
12		_this.exportPDF = false;
13		_this.exportJPG = false;
14		_this.exportSVG = false;
15		//_this.left;
16		_this.right = 0;
17		//_this.bottom;
18		_this.top = 0;
19		//_this.color;
20		_this.buttonRollOverColor = "#EFEFEF";
21		//_this.buttonColor = "#FFFFFF";
22		//_this.buttonRollOverAlpha = 0.5;
23		_this.textRollOverColor = "#CC0000";
24		_this.buttonTitle = "Save chart as an image";
25		_this.buttonAlpha = 0.75;
26		_this.imageFileName = "amChart";
27		_this.imageBackgroundColor = "#FFFFFF";
28	},
29
30	toCoordinate:function(value){
31		if(value === undefined){
32			return "auto";
33		}
34		if(String(value).indexOf("%") != -1){
35			return value;
36		}
37		else{
38			return value + "px";
39		}
40	},
41
42	init: function(){
43		var _this = this;
44
45		var formats = [];
46		if (_this.exportPNG) {
47			formats.push("png");
48		}
49		if (_this.exportPDF) {
50			formats.push("pdf");
51		}
52		if (_this.exportJPG) {
53			formats.push("jpg");
54		}
55		if (_this.exportSVG) {
56			formats.push("svg");
57		}
58
59		var menuItems = [];
60		if(formats.length == 1){
61			var format = formats[0];
62			menuItems.push({format:format, iconTitle:_this.buttonTitle, icon:_this.chart.pathToImages + _this.buttonIcon})
63		}
64		else if(formats.length > 1){
65			var subItems = [];
66			for(var i = 0; i < formats.length; i++){
67				subItems.push({format:formats[i], title:formats[i].toUpperCase()});
68			}
69			menuItems.push({onclick: function() {}, icon:_this.chart.pathToImages + _this.buttonIcon, items:subItems})
70		}
71
72
73		var color = _this.color;
74		if(color === undefined){
75			color = _this.chart.color;
76		}
77
78		var buttonColor = _this.buttonColor;
79		if(buttonColor === undefined){
80			buttonColor = "transparent";
81		}
82
83
84		_this.cfg = {
85			menuTop: _this.toCoordinate(_this.top),
86			menuLeft: _this.toCoordinate(_this.left),
87			menuRight: _this.toCoordinate(_this.right),
88			menuBottom: _this.toCoordinate(_this.bottom),
89			menuItems: menuItems,
90			menuItemStyle: {
91				backgroundColor: buttonColor,
92				opacity:_this.buttonAlpha,
93				rollOverBackgroundColor: _this.buttonRollOverColor,
94				color: color,
95				rollOverColor: _this.textRollOverColor,
96				paddingTop: '6px',
97				paddingRight: '6px',
98				paddingBottom: '6px',
99				paddingLeft: '6px',
100				marginTop: '0px',
101				marginRight: '0px',
102				marginBottom: '0px',
103				marginLeft: '0px',
104				textAlign: 'left',
105				textDecoration: 'none',
106				fontFamily: _this.chart.fontFamily,
107				fontSize: _this.chart.fontSize + 'px'
108			},
109			menuItemOutput: {
110				backgroundColor: _this.imageBackgroundColor,
111				fileName: _this.imageFileName,
112				format: 'png',
113				output: 'dataurlnewwindow',
114				render: 'browser',
115				dpi: 90,
116				onclick: function(instance, config, event) {
117					event.preventDefault();
118					// Polify SVG; needs to wait
119					instance.polifySVG();
120					instance.output(config);
121				}
122			},
123			removeImagery: false
124		};
125
126		_this.processing = {
127			buffer: [],
128			drawn: 0,
129			timer: 0
130		};
131
132		// Config dependency adaption
133		if (typeof(window.canvg) != 'undefined' && typeof(window.RGBColor) != 'undefined') {
134			_this.cfg.menuItemOutput.render = 'canvg';
135		}
136		if (typeof(window.saveAs) != 'undefined') {
137			_this.cfg.menuItemOutput.output = 'save';
138		}
139		if (AmCharts.isIE && AmCharts.IEversion < 10) {
140			_this.cfg.menuItemOutput.output = 'dataurlnewwindow';
141		}
142
143		// Merge given configs
144		var cfg = _this.userCFG;
145		if (cfg) {
146			cfg.menuItemOutput = AmCharts.extend(_this.cfg.menuItemOutput, cfg.menuItemOutput || {});
147			cfg.menuItemStyle = AmCharts.extend(_this.cfg.menuItemStyle, cfg.menuItemStyle || {});
148			_this.cfg = AmCharts.extend(_this.cfg, cfg);
149		}
150
151		// Add reference to chart
152		_this.chart.AmExport = _this;
153
154		// Listen to the drawer
155		_this.chart.addListener('rendered', function() {
156			_this.setup();
157		});
158
159		// DEBUG; Public reference
160		if (_this.DEBUG) {
161			window.AmExport = _this;
162		}
163	},
164
165
166	/*
167	Simple log function for internal purpose
168	@param **args
169	*/
170	log: function() {
171		console.log('AmExport: ', arguments);
172	},
173
174	/* PUBLIC
175	Prepares everything to get exported
176	@param none
177	*/
178	setup: function() {
179		var _this = this;
180
181		if (_this.DEBUG == 10) {
182			_this.log('SETUP START');
183		} // DEBUG
184
185
186		if (!AmCharts.isIE || (AmCharts.isIE && AmCharts.IEversion > 9)) {
187			// Build Buttons
188			_this.generateButtons();
189			if (_this.DEBUG == 10) {
190				_this.log('SETUP END');
191			} // DEBUG
192		} else {
193			if (_this.DEBUG == 10) {
194				_this.log('< IE10 NOT SUPPORTED');
195			} // DEBUG
196		}
197	},
198
199	/* PUBLIC
200	Decodes base64 string to binary array
201	@param base64_string
202	@copyright Eli Grey, http://eligrey.com and Devin Samarin, https://github.com/eboyjr
203	*/
204	generateBinaryArray: function(base64_string) {
205		var
206		len = base64_string.length,
207			buffer = new Uint8Array(len / 4 * 3 | 0),
208			i = 0,
209			outptr = 0,
210			last = [0, 0],
211			state = 0,
212			save = 0,
213			rank, code, undef, base64_ranks = new Uint8Array([
214				62, -1, -1, -1, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, 0, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51
215			]);
216		while (len--) {
217			code = base64_string.charCodeAt(i++);
218			rank = base64_ranks[code - 43];
219			if (rank !== 255 && rank !== undef) {
220				last[1] = last[0];
221				last[0] = code;
222				save = (save << 6) | rank;
223				state++;
224				if (state === 4) {
225					buffer[outptr++] = save >>> 16;
226					if (last[1] !== 61 /* padding character */ ) {
227						buffer[outptr++] = save >>> 8;
228					}
229					if (last[0] !== 61 /* padding character */ ) {
230						buffer[outptr++] = save;
231					}
232					state = 0;
233				}
234			}
235		}
236		// 2/3 chance there's going to be some null bytes at the end, but that
237		// doesn't really matter with most image formats.
238		// If it somehow matters for you, truncate the buffer up outptr.
239		return buffer;
240	},
241
242	/*
243	Creates blob object
244	@param base64_datastring string
245	@param type string
246	*/
247	generateBlob: function(datastring, type) {
248		var _this = this,
249			header_end = datastring.indexOf(',') + 1,
250			header = datastring.substring(0, header_end),
251			data = datastring,
252			blob = new Blob();
253
254		if (header.indexOf('base64') != -1) {
255			data = _this.generateBinaryArray(datastring.substring(header_end));
256		}
257
258		// Fake blob for IE
259		if (AmCharts.isIE && AmCharts.IEversion < 10) {
260			blob.data = data;
261			blob.size = data.length;
262			blob.type = type;
263			blob.encoding = 'base64';
264		} else {
265			blob = new Blob([data], {
266				type: type
267			});
268		}
269		return blob;
270	},
271
272	/*
273	Creates PDF object
274	@param config object
275	*/
276	generatePDF: function(cfg) {
277		var _this = this,
278			pdf = {
279				output: function() {
280					return '';
281				}
282			},
283			data = _this.canvas.toDataURL('image/jpeg'), // JSPDF ONLY SUPPORTS JPG
284			width = (_this.canvas.width * 25.4) / cfg.dpi,
285			height = (_this.canvas.height * 25.4) / cfg.dpi;
286
287		// Check
288		if (window.jsPDF) {
289			pdf = new jsPDF();
290			if (pdf.addImage) {
291				pdf.addImage(data, 'JPEG', 0, 0, width, height);
292			} else {
293				alert("Missing jsPDF plugin; Please add the 'addImage' plugin.");
294			}
295		} else {
296			alert("Missing jsPDF lib; Don't forget to add the addImage plugin.");
297		}
298
299		return pdf;
300	},
301
302	/*
303	Creates the CANVAS to receive the image data
304	@param format void()
305	@param callback; given callback function which returns the blob or datastring of the configured ouput type
306	*/
307	output: function(cfg, externalCallback) {
308		var _this = this;
309		cfg = AmCharts.extend(AmCharts.extend({}, _this.cfg.menuItemOutput), cfg || {});
310
311		/* PRIVATE
312		Callback function which gets called after the drawing process is done
313		@param none
314		*/
315		function internalCallback() {
316			var data = null;
317			var blob;
318			if (_this.DEBUG == 10) {
319				_this.log('OUTPUT', format);
320			} // DEBUG
321
322			// SVG
323			if (cfg.format == 'image/svg+xml' || cfg.format == 'svg') {
324				for (var i = 0; i < _this.processing.buffer.length; i++) {
325					data = new XMLSerializer().serializeToString(_this.processing.buffer[i][0]);
326					blob = _this.generateBlob(data, 'image/svg+xml');
327
328					if (cfg.output == 'save') {
329						saveAs(blob, cfg.fileName + '.svg');
330					} else if (cfg.output == 'datastring' || cfg.output == 'datauristring' || cfg.output == 'dataurlstring') {
331						blob = 'data:image/svg+xml;base64,' + btoa(data);
332					} else if (cfg.output == 'dataurlnewwindow') {
333						window.open('data:image/svg+xml;base64,' + btoa(data));
334					} else if (cfg.output == 'datauri' || cfg.output == 'dataurl') {
335						location.href = 'data:image/svg+xml;base64,' + btoa(data);
336					} else if (cfg.output == 'datastream') {
337						location.href = 'data:image/octet-stream;base64,' + btoa(data);
338					}
339
340					if (externalCallback)
341						externalCallback.apply(_this, [blob]);
342				}
343				// PDF
344			} else if (cfg.format == 'application/pdf' || cfg.format == 'pdf') {
345				data = _this.generatePDF(cfg).output('dataurlstring');
346				blob = _this.generateBlob(data, 'application/pdf');
347
348				if (cfg.output == 'save') {
349					saveAs(blob, cfg.fileName + '.pdf');
350				} else if (cfg.output == 'datastring' || cfg.output == 'datauristring' || cfg.output == 'dataurlstring') {
351					blob = data;
352				} else if (cfg.output == 'dataurlnewwindow') {
353					window.open(data);
354				} else if (cfg.output == 'datauri' || cfg.output == 'dataurl') {
355					location.href = data;
356				} else if (cfg.output == 'datastream') {
357					location.href = data.replace('application/pdf', 'application/octet-stream');
358				}
359
360				if (externalCallback)
361					externalCallback.apply(_this, [blob]);
362
363				// PNG
364			} else if (cfg.format == 'image/png' || cfg.format == 'png') {
365				data = _this.canvas.toDataURL('image/png');
366				blob = _this.generateBlob(data, 'image/png');
367
368				if (cfg.output == 'save') {
369					saveAs(blob, cfg.fileName + '.png');
370				} else if (cfg.output == 'datastring' || cfg.output == 'datauristring' || cfg.output == 'dataurlstring') {
371					blob = data;
372				} else if (cfg.output == 'dataurlnewwindow') {
373					window.open(data);
374				} else if (cfg.output == 'datauri' || cfg.output == 'dataurl') {
375					location.href = data;
376				} else if (cfg.output == 'datastream') {
377					location.href = data.replace('image/png', 'image/octet-stream');
378				}
379
380				if (externalCallback)
381					externalCallback.apply(_this, [blob]);
382
383				// JPG
384			} else if (cfg.format == 'image/jpeg' || cfg.format == 'jpeg' || cfg.format == 'jpg') {
385				data = _this.canvas.toDataURL('image/jpeg');
386				blob = _this.generateBlob(data, 'image/jpeg');
387
388				if (cfg.output == 'save') {
389					saveAs(blob, cfg.fileName + '.jpg');
390				} else if (cfg.output == 'datastring' || cfg.output == 'datauristring' || cfg.output == 'dataurlstring') {
391					blob = data;
392				} else if (cfg.output == 'dataurlnewwindow') {
393					window.open(data);
394				} else if (cfg.output == 'datauri' || cfg.output == 'dataurl') {
395					location.href = data;
396				} else if (cfg.output == 'datastream') {
397					location.href = data.replace('image/jpeg', 'image/octet-stream');
398				}
399
400				if (externalCallback)
401					externalCallback.apply(_this, [blob]);
402			}
403
404		}
405
406		return _this.generateOutput(cfg, internalCallback);
407	},
408
409	/* PUBLIC
410	Polifies missing attributes to the SVG and replaces images to embedded base64 images
411	@param none
412	*/
413	polifySVG: function() {
414		var _this = this;
415		var svgs = _this.chart.div.getElementsByTagName('svg');
416
417		// Recursive function to force the attributes
418		function recursiveChange(svg, tag) {
419			var items = svg.getElementsByTagName(tag);
420
421			for (var i = 0; i < items.length; i++) {
422
423				if (_this.cfg.removeImagery) {
424					items[i].parentNode.removeChild(items[i]);
425
426				} else {
427					var image = document.createElement('img');
428					var canvas = document.createElement('canvas');
429					var ctx = canvas.getContext('2d');
430
431					canvas.width = items[i].getAttribute('width');
432					canvas.height = items[i].getAttribute('height');
433					image.src = items[i].getAttribute('xlink:href');
434					image.width = items[i].getAttribute('width');
435					image.height = items[i].getAttribute('height');
436
437					try {
438						ctx.drawImage(image, 0, 0, image.width, image.height);
439						datastring = canvas.toDataURL(); // image.src; // canvas.toDataURL(); //
440					} catch (err) {
441						datastring = image.src; // image.src; // canvas.toDataURL(); //
442
443						_this.log('Tainted canvas, reached browser CORS security; origin from imagery must be equal to the server!');
444						throw new Error(err);
445					}
446
447					items[i].setAttribute('xlink:href', datastring);
448				}
449
450				if (_this.DEBUG == 10) {
451					_this.log('POLIFIED', items[i]);
452				} // DEBUG
453			}
454		}
455
456		// Loop through svgs to add some standardization
457		for (var i = 0; i < svgs.length; i++) {
458			var parent = svgs[i].parentNode;
459
460			// Put some attrs to it; fixed 20/03/14 xmlns is required to produce a valid svg file
461			if (AmCharts.IEversion == 0) {
462				svgs[i].setAttribute('xmlns', 'http://www.w3.org/2000/svg');
463				//svgs[i].setAttribute('xmlns:xlink','http://www.w3.org/1999/xlink');
464			}
465			//svgs[i].setAttribute('width',parent.style.width);
466			//svgs[i].setAttribute('height',parent.style.height);
467
468			// DEBUG
469			if (_this.DEBUG == 10) {
470				_this.log('POLIFIED', svgs[i]);
471			}
472
473			// Force link adaption
474			recursiveChange(svgs[i], 'pattern');
475			recursiveChange(svgs[i], 'image');
476
477			_this.svgs.push(svgs[i]);
478		}
479
480		return svgs;
481	},
482
483	/* PUBLIC
484	Generates the canvas with the given SVGs and configured renderer
485	@param callback; function(); gets called after drawing process on the canvas has been finished
486	*/
487	generateOutput: function(cfg, callback) {
488		var _this = this,
489			svgs = _this.chart.div.getElementsByTagName('svg'),
490			canvas = document.createElement('canvas'),
491			context = canvas.getContext('2d'),
492			offset = {
493				y: 0,
494				x: 0
495			},
496			tmp = {};
497
498		// Reset
499		_this.processing.buffer = [];
500		_this.processing.drawn = 0;
501		_this.canvas = canvas;
502
503		// Walkthroug SVGs
504		if (_this.DEBUG == 10) {
505			_this.log('START EXPORT');
506		} // DEBUG
507		if (_this.DEBUG == 10) {
508			_this.log('START BUFFERING');
509		} // DEBUG
510		for (var i = 0; i < svgs.length; i++) {
511			var parent = svgs[i].parentNode,
512				svgX = Number(parent.style.left.slice(0, -2)),
513				svgY = Number(parent.style.top.slice(0, -2));
514			tmp = AmCharts.extend({}, offset);
515
516			// Overtake parent position if given; fixed 20/03/14 distinguish between relativ and others
517			if (parent.style.position == 'relative') {
518				offset.x = svgX ? svgX : offset.x;
519				offset.y = svgY ? svgY : offset.y;
520			} else {
521				offset.x = svgX;
522				offset.y = svgY;
523			}
524
525			_this.processing.buffer.push([svgs[i], AmCharts.extend({}, offset)]);
526
527			// Put back from "cache"
528			if (svgY && svgX) {
529				offset = tmp;
530
531				// New offset for next one
532			} else {
533				offset.y += svgY ? 0 : parent.offsetHeight;
534			}
535
536			if (_this.DEBUG == 10) {
537				_this.log('BUFFERED', svgs[i], offset);
538			} // DEBUG
539		}
540		if (_this.DEBUG == 10) {
541			_this.log('END BUFFERING');
542		} // DEBUG
543
544		// Apply background
545		if (_this.DEBUG == 10) {
546			_this.log('START DRAWING', cfg.render);
547		} // DEBUG
548		if (_this.DEBUG == 10) {
549			_this.log('FILL BACKGROUND');
550		} // DEBUG
551		canvas.id = AmCharts.getUniqueId();
552		canvas.width = _this.chart.divRealWidth;
553		canvas.height = _this.chart.divRealHeight;
554
555		// Set given background; jpeg default
556		if (cfg.backgroundColor || cfg.format == 'image/jpeg') {
557			context.fillStyle = cfg.backgroundColor || '#FFFFFF';
558			context.fillRect(0, 0, canvas.width, canvas.height);
559		}
560
561		/* PRIVATE
562		Recursive function to draw the images to the canvas;
563		@param none;
564		*/
565		function drawItWhenItsLoaded() {
566			var img, buffer, offset, source;
567
568			// DRAWING PROCESS DONE
569			if (_this.processing.buffer.length == _this.processing.drawn) {
570				if (_this.DEBUG == 10) {
571					_this.log('END DRAWING');
572				} // DEBUG
573				return callback();
574
575				// LOOPING LUI
576			} else {
577				if (_this.DEBUG == 10) {
578					_this.log('DRAW', _this.processing.drawn + 1, 'OF', _this.processing.buffer.length);
579				} // DEBUG
580
581				buffer = _this.processing.buffer[_this.processing.drawn];
582				source = new XMLSerializer().serializeToString(buffer[0]); //source = 'data:image/svg+xml;base64,' + btoa();
583				offset = buffer[1];
584
585				if (_this.DEBUG == 10) {
586					_this.log('SOURCE', source);
587				} // DEBUG
588
589				// NATIVE
590				if (cfg.render == 'browser') {
591					img = new Image();
592					img.id = AmCharts.getUniqueId();
593					source = 'data:image/svg+xml;base64,' + btoa(source);
594
595					//img.crossOrigin	= "Anonymous";
596					img.onload = function() {
597						context.drawImage(this, buffer[1].x, buffer[1].y);
598						_this.processing.drawn++;
599
600						if (_this.DEBUG == 10) {
601							_this.log('ONLOAD', this);
602						} // DEBUG
603						drawItWhenItsLoaded();
604					};
605					img.onerror = function() {
606						if (_this.DEBUG == 10) {
607							_this.log('ONERROR', this);
608						} // DEBUG
609						context.drawImage(this, buffer[1].x, buffer[1].y);
610						_this.processing.drawn++;
611						drawItWhenItsLoaded();
612					};
613					img.src = source;
614
615					if (_this.DEBUG == 10) {
616						_this.log('ADD', img);
617					} // DEBUG
618					if (img.complete || typeof(img.complete) == 'undefined' || img.complete === undefined) {
619						if (_this.DEBUG == 10) {
620							_this.log('FORCE ONLOAD', img);
621						} // DEBUG
622						img.src = "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///ywAAAAAAQABAAACAUwAOw==";
623						img.src = source;
624					}
625
626					// CANVG
627				} else if (cfg.render == 'canvg') {
628					canvg(canvas, source, {
629						offsetX: offset.x,
630						offsetY: offset.y,
631						ignoreMouse: true,
632						ignoreAnimation: true,
633						ignoreDimensions: true,
634						ignoreClear: true,
635						renderCallback: function() {
636							_this.processing.drawn++;
637							drawItWhenItsLoaded();
638						}
639					});
640				}
641			}
642		}
643		return drawItWhenItsLoaded();
644	},
645
646	/*
647	Generates the export menu to trigger the exportation
648	@param none;
649	*/
650	generateButtons: function() {
651		var _this = this,
652			div = document.createElement('div'),
653			lvl = 0;
654
655		// Push sublings
656		function createList(items) {
657			var ul = document.createElement('ul');
658
659			ul.setAttribute('style', 'list-style: none; margin: 0; padding: 0;');
660
661			// Walkthrough items
662			for (var i = 0; i < items.length; i++) {
663				var li = document.createElement('li'),
664					img = document.createElement('img'),
665					a = document.createElement('a'),
666					item = items[i],
667					children = null,
668					itemStyle = AmCharts.extend(AmCharts.extend({}, _this.cfg.menuItemStyle), items[i]);
669
670				// MERGE CFG
671				item = AmCharts.extend(AmCharts.extend({}, _this.cfg.menuItemOutput), item);
672
673				// ICON
674				if (item['icon']) {
675					img.alt = '';
676					img.src = item['icon'];
677					img.setAttribute('style', 'margin: 0 auto;border: none;outline: none');
678					if (item['iconTitle']) {
679						img.title = item['iconTitle'];
680					}
681					a.appendChild(img);
682				}
683
684				// TITLE; STYLING
685				a.href = '#';
686				if (item['title']) {
687					img.setAttribute('style', 'margin-right: 5px;');
688					a.innerHTML += item.title;
689				}
690				a.setAttribute('style', 'display: block;');
691				AmCharts.extend(a.style, itemStyle);
692
693				// ONCLICK
694				a.onclick = item.onclick.bind(a, _this, item);
695				li.appendChild(a);
696
697				// APPEND SIBLINGS
698				if (item.items) {
699					children = createList(item.items);
700					li.appendChild(children);
701
702					li.onmouseover = function() {
703						children.style.display = 'block';
704					};
705					li.onmouseout = function() {
706						children.style.display = 'none';
707					};
708					children.style.display = 'none';
709				}
710
711				// Append to parent
712				ul.appendChild(li);
713
714				// Apply hover
715				a.onmouseover = function() {
716					this.style.backgroundColor = itemStyle.rollOverBackgroundColor;
717					this.style.color = itemStyle.rollOverColor;
718					this.style.borderColor = itemStyle.rollOverBorderColor;
719				};
720				a.onmouseout = function() {
721					this.style.backgroundColor = itemStyle.backgroundColor;
722					this.style.color = itemStyle.color;
723					this.style.borderColor = itemStyle.borderColor;
724				};
725			}
726			lvl++;
727
728			if (_this.DEBUG == 10) {
729				_this.log('MENU', ul);
730			} // DEBUG
731
732			return ul;
733		}
734
735		// Style wrapper; Push into chart div
736		div.setAttribute('style', 'width:39px; height:28px; position: absolute;top:' + _this.cfg.menuTop + ';right:' + _this.cfg.menuRight + ';bottom:' + _this.cfg.menuBottom + ';left:' + _this.cfg.menuLeft + ';box-shadow:0px 0px 1px 0px rgba(0,0,0,0);');
737		div.setAttribute('class', 'amExportButton');
738		div.appendChild(createList(_this.cfg.menuItems));
739		//_this.chart.div.style.position = 'relative';
740		_this.chart.containerDiv.appendChild(div);
741	}
742});

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.