Commit inicial Ventas Productivo
This commit is contained in:
@@ -0,0 +1,855 @@
|
||||
AmCharts.AmExport = AmCharts.Class({
|
||||
construct: function(chart, cfg, init ) {
|
||||
var _this = this;
|
||||
_this.DEBUG = false;
|
||||
_this.chart = chart;
|
||||
_this.canvas = null;
|
||||
_this.svgs = [];
|
||||
_this.userCFG = cfg;
|
||||
|
||||
_this.buttonIcon = 'export.png';
|
||||
_this.exportPNG = true;
|
||||
_this.exportPDF = false;
|
||||
_this.exportJPG = false;
|
||||
_this.exportSVG = false;
|
||||
//_this.left;
|
||||
_this.right = 0;
|
||||
//_this.bottom;
|
||||
_this.top = 0;
|
||||
//_this.color;
|
||||
_this.buttonRollOverColor = "#EFEFEF";
|
||||
//_this.buttonColor = "#FFFFFF";
|
||||
//_this.buttonRollOverAlpha = 0.5;
|
||||
_this.textRollOverColor = "#CC0000";
|
||||
_this.buttonTitle = "Save chart as an image";
|
||||
_this.buttonAlpha = 0.75;
|
||||
_this.imageFileName = "amChart";
|
||||
_this.imageBackgroundColor = "#FFFFFF";
|
||||
|
||||
if (init) {
|
||||
_this.init();
|
||||
}
|
||||
},
|
||||
|
||||
toCoordinate:function(value){
|
||||
if(value === undefined){
|
||||
return "auto";
|
||||
}
|
||||
if(String(value).indexOf("%") != -1){
|
||||
return value;
|
||||
}
|
||||
else{
|
||||
return value + "px";
|
||||
}
|
||||
},
|
||||
|
||||
init: function(){
|
||||
var _this = this;
|
||||
|
||||
var formats = [];
|
||||
if (_this.exportPNG) {
|
||||
formats.push("png");
|
||||
}
|
||||
if (_this.exportPDF) {
|
||||
formats.push("pdf");
|
||||
}
|
||||
if (_this.exportJPG) {
|
||||
formats.push("jpg");
|
||||
}
|
||||
if (_this.exportSVG) {
|
||||
formats.push("svg");
|
||||
}
|
||||
|
||||
var menuItems = [];
|
||||
if(formats.length == 1){
|
||||
var format = formats[0];
|
||||
menuItems.push({format:format, iconTitle:_this.buttonTitle, icon:_this.chart.pathToImages + _this.buttonIcon})
|
||||
}
|
||||
else if(formats.length > 1){
|
||||
var subItems = [];
|
||||
for(var i = 0; i < formats.length; i++){
|
||||
subItems.push({format:formats[i], title:formats[i].toUpperCase()});
|
||||
}
|
||||
menuItems.push({onclick: function() {}, icon:_this.chart.pathToImages + _this.buttonIcon, items:subItems})
|
||||
}
|
||||
|
||||
|
||||
var color = _this.color;
|
||||
if(color === undefined){
|
||||
color = _this.chart.color;
|
||||
}
|
||||
|
||||
var buttonColor = _this.buttonColor;
|
||||
if(buttonColor === undefined){
|
||||
buttonColor = "transparent";
|
||||
}
|
||||
|
||||
|
||||
_this.cfg = {
|
||||
menuTop : _this.toCoordinate(_this.top),
|
||||
menuLeft : _this.toCoordinate(_this.left),
|
||||
menuRight : _this.toCoordinate(_this.right),
|
||||
menuBottom : _this.toCoordinate(_this.bottom),
|
||||
menuItems : menuItems,
|
||||
menuItemStyle: {
|
||||
backgroundColor : buttonColor,
|
||||
opacity :_this.buttonAlpha,
|
||||
rollOverBackgroundColor : _this.buttonRollOverColor,
|
||||
color : color,
|
||||
rollOverColor : _this.textRollOverColor,
|
||||
paddingTop : '6px',
|
||||
paddingRight : '6px',
|
||||
paddingBottom : '6px',
|
||||
paddingLeft : '6px',
|
||||
marginTop : '0px',
|
||||
marginRight : '0px',
|
||||
marginBottom : '0px',
|
||||
marginLeft : '0px',
|
||||
textAlign : 'left',
|
||||
textDecoration : 'none',
|
||||
fontFamily : _this.chart.fontFamily,
|
||||
fontSize : _this.chart.fontSize + 'px'
|
||||
},
|
||||
menuItemOutput: {
|
||||
backgroundColor : _this.imageBackgroundColor,
|
||||
fileName : _this.imageFileName,
|
||||
format : 'png',
|
||||
output : 'dataurlnewwindow',
|
||||
render : 'browser',
|
||||
dpi : 90,
|
||||
onclick : function(instance, config, event) {
|
||||
event.preventDefault();
|
||||
instance.output(config);
|
||||
}
|
||||
},
|
||||
removeImagery: true
|
||||
};
|
||||
|
||||
_this.processing = {
|
||||
buffer: [],
|
||||
drawn: 0,
|
||||
timer: 0
|
||||
};
|
||||
|
||||
// Config dependency adaption
|
||||
if (typeof(window.canvg) != 'undefined' && typeof(window.RGBColor) != 'undefined') {
|
||||
_this.cfg.menuItemOutput.render = 'canvg';
|
||||
}
|
||||
if (typeof(window.saveAs) != 'undefined') {
|
||||
_this.cfg.menuItemOutput.output = 'save';
|
||||
}
|
||||
if (AmCharts.isIE && AmCharts.IEversion < 10) {
|
||||
_this.cfg.menuItemOutput.output = 'dataurlnewwindow';
|
||||
}
|
||||
|
||||
// Merge given configs
|
||||
var cfg = _this.userCFG;
|
||||
if (cfg) {
|
||||
cfg.menuItemOutput = AmCharts.extend(_this.cfg.menuItemOutput, cfg.menuItemOutput || {});
|
||||
cfg.menuItemStyle = AmCharts.extend(_this.cfg.menuItemStyle, cfg.menuItemStyle || {});
|
||||
_this.cfg = AmCharts.extend(_this.cfg, cfg);
|
||||
}
|
||||
|
||||
// Add reference to chart
|
||||
_this.chart.AmExport = _this;
|
||||
|
||||
// Listen to the drawer
|
||||
_this.chart.addListener('rendered', function() {
|
||||
_this.setup();
|
||||
});
|
||||
|
||||
// DEBUG; Public reference
|
||||
if (_this.DEBUG) {
|
||||
window.AmExport = _this;
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
/*
|
||||
Simple log function for internal purpose
|
||||
@param **args
|
||||
*/
|
||||
log: function() {
|
||||
console.log('AmExport: ', arguments);
|
||||
},
|
||||
|
||||
/* PUBLIC
|
||||
Prepares everything to get exported
|
||||
@param none
|
||||
*/
|
||||
setup: function() {
|
||||
var _this = this;
|
||||
|
||||
if (_this.DEBUG == 10) {
|
||||
_this.log('SETUP START');
|
||||
} // DEBUG
|
||||
|
||||
|
||||
if (!AmCharts.isIE || (AmCharts.isIE && AmCharts.IEversion > 9)) {
|
||||
// Build Buttons
|
||||
_this.generateButtons();
|
||||
if (_this.DEBUG == 10) {
|
||||
_this.log('SETUP END');
|
||||
} // DEBUG
|
||||
} else {
|
||||
if (_this.DEBUG == 10) {
|
||||
_this.log('< IE10 NOT SUPPORTED');
|
||||
} // DEBUG
|
||||
}
|
||||
},
|
||||
|
||||
/* PUBLIC
|
||||
Decodes base64 string to binary array
|
||||
@param base64_string
|
||||
@copyright Eli Grey, http://eligrey.com and Devin Samarin, https://github.com/eboyjr
|
||||
*/
|
||||
generateBinaryArray: function(base64_string) {
|
||||
var
|
||||
len = base64_string.length,
|
||||
buffer = new Uint8Array(len / 4 * 3 | 0),
|
||||
i = 0,
|
||||
outptr = 0,
|
||||
last = [0, 0],
|
||||
state = 0,
|
||||
save = 0,
|
||||
rank, code, undef, base64_ranks = new Uint8Array([
|
||||
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
|
||||
]);
|
||||
while (len--) {
|
||||
code = base64_string.charCodeAt(i++);
|
||||
rank = base64_ranks[code - 43];
|
||||
if (rank !== 255 && rank !== undef) {
|
||||
last[1] = last[0];
|
||||
last[0] = code;
|
||||
save = (save << 6) | rank;
|
||||
state++;
|
||||
if (state === 4) {
|
||||
buffer[outptr++] = save >>> 16;
|
||||
if (last[1] !== 61 /* padding character */ ) {
|
||||
buffer[outptr++] = save >>> 8;
|
||||
}
|
||||
if (last[0] !== 61 /* padding character */ ) {
|
||||
buffer[outptr++] = save;
|
||||
}
|
||||
state = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
// 2/3 chance there's going to be some null bytes at the end, but that
|
||||
// doesn't really matter with most image formats.
|
||||
// If it somehow matters for you, truncate the buffer up outptr.
|
||||
return buffer;
|
||||
},
|
||||
|
||||
/*
|
||||
Creates blob object
|
||||
@param base64_datastring string
|
||||
@param type string
|
||||
*/
|
||||
generateBlob: function(datastring, type) {
|
||||
var _this = this,
|
||||
header_end = type!='image/svg+xml'?datastring.indexOf(',') + 1:0,
|
||||
header = datastring.substring(0, header_end),
|
||||
data = datastring,
|
||||
blob = new Blob();
|
||||
|
||||
if (header.indexOf('base64') != -1) {
|
||||
data = _this.generateBinaryArray(datastring.substring(header_end));
|
||||
}
|
||||
|
||||
// Fake blob for IE
|
||||
if (AmCharts.isIE && AmCharts.IEversion < 10) {
|
||||
blob.data = data;
|
||||
blob.size = data.length;
|
||||
blob.type = type;
|
||||
blob.encoding = 'base64';
|
||||
} else {
|
||||
blob = new Blob([data], {
|
||||
type: type
|
||||
});
|
||||
}
|
||||
return blob;
|
||||
},
|
||||
|
||||
/*
|
||||
Creates PDF object
|
||||
@param config object
|
||||
*/
|
||||
generatePDF: function(cfg) {
|
||||
var _this = this,
|
||||
pdf = {
|
||||
output: function() {
|
||||
return '';
|
||||
}
|
||||
},
|
||||
data = _this.canvas.toDataURL('image/jpeg'), // JSPDF ONLY SUPPORTS JPG
|
||||
width = (_this.canvas.width * 25.4) / cfg.dpi,
|
||||
height = (_this.canvas.height * 25.4) / cfg.dpi;
|
||||
|
||||
// Check
|
||||
if (window.jsPDF) {
|
||||
pdf = new jsPDF();
|
||||
if (pdf.addImage) {
|
||||
pdf.addImage(data, 'JPEG', 0, 0, width, height);
|
||||
} else {
|
||||
alert("Missing jsPDF plugin; Please add the 'addImage' plugin.");
|
||||
}
|
||||
} else {
|
||||
alert("Missing jsPDF lib; Don't forget to add the addImage plugin.");
|
||||
}
|
||||
|
||||
return pdf;
|
||||
},
|
||||
|
||||
/*
|
||||
Creates the CANVAS to receive the image data
|
||||
@param format void()
|
||||
@param callback; given callback function which returns the blob or datastring of the configured ouput type
|
||||
*/
|
||||
output: function(cfg, externalCallback) {
|
||||
var _this = this;
|
||||
cfg = AmCharts.extend(AmCharts.extend({}, _this.cfg.menuItemOutput), cfg || {});
|
||||
|
||||
// Prepare chart
|
||||
if(_this.chart.prepareForExport){
|
||||
_this.chart.prepareForExport();
|
||||
}
|
||||
|
||||
/* PRIVATE
|
||||
Callback function which gets called after the drawing process is done
|
||||
@param none
|
||||
*/
|
||||
function internalCallback() {
|
||||
var data = null;
|
||||
var blob;
|
||||
if (_this.DEBUG == 10) {
|
||||
_this.log('OUTPUT', cfg.format);
|
||||
} // DEBUG
|
||||
|
||||
// SVG
|
||||
if (cfg.format == 'image/svg+xml' || cfg.format == 'svg') {
|
||||
data = _this.generateSVG();
|
||||
blob = _this.generateBlob(data, 'image/svg+xml');
|
||||
|
||||
if (cfg.output == 'save') {
|
||||
saveAs(blob, cfg.fileName + '.svg');
|
||||
} else if (cfg.output == 'datastring' || cfg.output == 'datauristring' || cfg.output == 'dataurlstring') {
|
||||
blob = 'data:image/svg+xml;base64,' + btoa(data);
|
||||
} else if (cfg.output == 'dataurlnewwindow') {
|
||||
window.open('data:image/svg+xml;base64,' + btoa(data));
|
||||
} else if (cfg.output == 'datauri' || cfg.output == 'dataurl') {
|
||||
location.href = 'data:image/svg+xml;base64,' + btoa(data);
|
||||
} else if (cfg.output == 'datastream') {
|
||||
location.href = 'data:image/octet-stream;base64,' + data;
|
||||
}
|
||||
|
||||
if (externalCallback)
|
||||
externalCallback.apply(_this, [blob]);
|
||||
|
||||
// PDF
|
||||
} else if (cfg.format == 'application/pdf' || cfg.format == 'pdf') {
|
||||
data = _this.generatePDF(cfg).output('dataurlstring');
|
||||
blob = _this.generateBlob(data, 'application/pdf');
|
||||
|
||||
if (cfg.output == 'save') {
|
||||
saveAs(blob, cfg.fileName + '.pdf');
|
||||
} else if (cfg.output == 'datastring' || cfg.output == 'datauristring' || cfg.output == 'dataurlstring') {
|
||||
blob = data;
|
||||
} else if (cfg.output == 'dataurlnewwindow') {
|
||||
window.open(data);
|
||||
} else if (cfg.output == 'datauri' || cfg.output == 'dataurl') {
|
||||
location.href = data;
|
||||
} else if (cfg.output == 'datastream') {
|
||||
location.href = data.replace('application/pdf', 'application/octet-stream');
|
||||
}
|
||||
|
||||
if (externalCallback)
|
||||
externalCallback.apply(_this, [blob]);
|
||||
|
||||
// PNG
|
||||
} else if (cfg.format == 'image/png' || cfg.format == 'png') {
|
||||
data = _this.canvas.toDataURL('image/png');
|
||||
blob = _this.generateBlob(data, 'image/png');
|
||||
|
||||
if (cfg.output == 'save') {
|
||||
saveAs(blob, cfg.fileName + '.png');
|
||||
} else if (cfg.output == 'datastring' || cfg.output == 'datauristring' || cfg.output == 'dataurlstring') {
|
||||
blob = data;
|
||||
} else if (cfg.output == 'dataurlnewwindow') {
|
||||
window.open(data);
|
||||
} else if (cfg.output == 'datauri' || cfg.output == 'dataurl') {
|
||||
location.href = data;
|
||||
} else if (cfg.output == 'datastream') {
|
||||
location.href = data.replace('image/png', 'image/octet-stream');
|
||||
}
|
||||
|
||||
if (externalCallback)
|
||||
externalCallback.apply(_this, [blob]);
|
||||
|
||||
// JPG
|
||||
} else if (cfg.format == 'image/jpeg' || cfg.format == 'jpeg' || cfg.format == 'jpg') {
|
||||
data = _this.canvas.toDataURL('image/jpeg');
|
||||
blob = _this.generateBlob(data, 'image/jpeg');
|
||||
|
||||
if (cfg.output == 'save') {
|
||||
saveAs(blob, cfg.fileName + '.jpg');
|
||||
} else if (cfg.output == 'datastring' || cfg.output == 'datauristring' || cfg.output == 'dataurlstring') {
|
||||
blob = data;
|
||||
} else if (cfg.output == 'dataurlnewwindow') {
|
||||
window.open(data);
|
||||
} else if (cfg.output == 'datauri' || cfg.output == 'dataurl') {
|
||||
location.href = data;
|
||||
} else if (cfg.output == 'datastream') {
|
||||
location.href = data.replace('image/jpeg', 'image/octet-stream');
|
||||
}
|
||||
|
||||
if (externalCallback)
|
||||
externalCallback.apply(_this, [blob]);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return _this.generateOutput(cfg, internalCallback);
|
||||
},
|
||||
|
||||
/* PUBLIC
|
||||
Polifies missing attributes to the SVG and replaces images to embedded base64 images
|
||||
@param none
|
||||
*/
|
||||
polifySVG: function(svg) {
|
||||
var _this = this;
|
||||
|
||||
// Recursive function to force the attributes
|
||||
function recursiveChange(svg, tag) {
|
||||
var items = svg.getElementsByTagName(tag);
|
||||
var i = items.length;
|
||||
|
||||
while(i--) {
|
||||
if (_this.cfg.removeImagery) {
|
||||
items[i].parentNode.removeChild(items[i]);
|
||||
|
||||
} else {
|
||||
var image = document.createElement('img');
|
||||
var canvas = document.createElement('canvas');
|
||||
var ctx = canvas.getContext('2d');
|
||||
|
||||
canvas.width = items[i].getAttribute('width');
|
||||
canvas.height = items[i].getAttribute('height');
|
||||
image.src = items[i].getAttribute('xlink:href');
|
||||
image.width = items[i].getAttribute('width');
|
||||
image.height = items[i].getAttribute('height');
|
||||
|
||||
try {
|
||||
ctx.drawImage(image, 0, 0, image.width, image.height);
|
||||
datastring = canvas.toDataURL(); // image.src; // canvas.toDataURL(); //
|
||||
} catch (err) {
|
||||
datastring = image.src; // image.src; // canvas.toDataURL(); //
|
||||
|
||||
_this.log('Tainted canvas, reached browser CORS security; origin from imagery must be equal to the server!');
|
||||
throw new Error(err);
|
||||
}
|
||||
|
||||
items[i].setAttribute('xlink:href', datastring);
|
||||
}
|
||||
|
||||
if (_this.DEBUG == 10) {
|
||||
_this.log('POLIFIED', items[i]);
|
||||
} // DEBUG
|
||||
}
|
||||
}
|
||||
|
||||
// Put some attrs to it; fixed 20/03/14 xmlns is required to produce a valid svg file
|
||||
if (AmCharts.IEversion == 0) {
|
||||
svg.setAttribute('xmlns', 'http://www.w3.org/2000/svg');
|
||||
if ( !_this.cfg.removeImagery ) {
|
||||
svg.setAttribute('xmlns:xlink','http://www.w3.org/1999/xlink');
|
||||
}
|
||||
}
|
||||
|
||||
// DEBUG
|
||||
if (_this.DEBUG == 10) {
|
||||
_this.log('POLIFIED', svg);
|
||||
}
|
||||
|
||||
// Force link adaption
|
||||
recursiveChange(svg, 'pattern');
|
||||
recursiveChange(svg, 'image');
|
||||
|
||||
_this.svgs.push(svg);
|
||||
|
||||
return svg;
|
||||
},
|
||||
|
||||
|
||||
/* PUBLIC
|
||||
Stacks multiple SVGs into one
|
||||
@param none
|
||||
*/
|
||||
generateSVG: function() {
|
||||
var _this = this;
|
||||
var context = document.createElement('svg');
|
||||
context.setAttribute('xmlns', 'http://www.w3.org/2000/svg');
|
||||
context.setAttribute('xmlns:xlink','http://www.w3.org/1999/xlink');
|
||||
|
||||
for (var i = 0; i < _this.processing.buffer.length; i++) {
|
||||
var group = document.createElement('g'),
|
||||
data = _this.processing.buffer[i];
|
||||
|
||||
data[0].setAttribute('xmlns', 'http://www.w3.org/2000/svg');
|
||||
data[0].setAttribute('xmlns:xlink','http://www.w3.org/1999/xlink');
|
||||
|
||||
group.setAttribute('transform', 'translate('+data[1].x+','+data[1].y+')');
|
||||
group.appendChild(data[0]);
|
||||
context.appendChild(group);
|
||||
}
|
||||
|
||||
return new XMLSerializer().serializeToString(context);
|
||||
},
|
||||
|
||||
/* PUBLIC
|
||||
Generates the canvas with the given SVGs and configured renderer
|
||||
@param callback; function(); gets called after drawing process on the canvas has been finished
|
||||
*/
|
||||
generateOutput: function(cfg, callback) {
|
||||
var _this = this,
|
||||
coll = [],
|
||||
svgs = [],
|
||||
canvas = document.createElement('canvas'),
|
||||
context = canvas.getContext('2d'),
|
||||
offset = {
|
||||
y: 0,
|
||||
x: 0
|
||||
},
|
||||
|
||||
// Push svgs into array
|
||||
coll = _this.chart.div.getElementsByTagName('svg');
|
||||
for ( var i = 0; i < coll.length; i++ ) svgs.push(coll[i]);
|
||||
|
||||
// Add external legend
|
||||
if ( _this.chart.legend && _this.chart.legend.position == 'outside' ) {
|
||||
_this.chart.legend.container.container.externalLegend = true
|
||||
svgs.push(_this.chart.legend.container.container);
|
||||
|
||||
// Add offset
|
||||
if ( _this.cfg.legendPosition == 'left' ) {
|
||||
offset.x = _this.chart.legend.div.offsetWidth;
|
||||
} else if ( _this.cfg.legendPosition == 'top' ) {
|
||||
offset.y = _this.chart.legend.div.offsetHeight;
|
||||
} else if ( typeof _this.cfg.legendPosition == 'object' ) {
|
||||
offset.y = _this.cfg.legendPosition.chartTop;
|
||||
offset.x = _this.cfg.legendPosition.chartLeft;
|
||||
}
|
||||
}
|
||||
|
||||
// Reset
|
||||
_this.processing.buffer = [];
|
||||
_this.processing.drawn = 0;
|
||||
_this.canvas = canvas;
|
||||
_this.svgs = [];
|
||||
|
||||
// Walkthroug SVGs
|
||||
if (_this.DEBUG == 10) {
|
||||
_this.log('START EXPORT');
|
||||
} // DEBUG
|
||||
if (_this.DEBUG == 10) {
|
||||
_this.log('START BUFFERING');
|
||||
} // DEBUG
|
||||
for (var i = 0; i < svgs.length; i++) {
|
||||
var parent = svgs[i].parentNode,
|
||||
svgX = Number(parent.style.left.slice(0, -2)),
|
||||
svgY = Number(parent.style.top.slice(0, -2)),
|
||||
svgClone = _this.polifySVG(svgs[i].cloneNode(true)),
|
||||
tmp = AmCharts.extend({}, offset);
|
||||
|
||||
// Add external legend
|
||||
if ( svgs[i].externalLegend ) {
|
||||
if ( _this.cfg.legendPosition == 'right' ) {
|
||||
offset.y = 0;
|
||||
offset.x = _this.chart.divRealWidth;
|
||||
|
||||
} else if ( _this.cfg.legendPosition == 'bottom' ) {
|
||||
offset.y = svgY ? svgY : offset.y;
|
||||
|
||||
} else if ( typeof _this.cfg.legendPosition == 'object' ) {
|
||||
offset.x = _this.cfg.legendPosition.left;
|
||||
offset.y = _this.cfg.legendPosition.top;
|
||||
|
||||
} else {
|
||||
offset.x = 0;
|
||||
offset.y = 0;
|
||||
}
|
||||
|
||||
// Overtake parent position if given; fixed 20/03/14 distinguish between relativ and others
|
||||
} else {
|
||||
if ( parent.style.position == 'relative' ) {
|
||||
offset.x = svgX ? svgX : offset.x;
|
||||
offset.y = svgY ? svgY : offset.y;
|
||||
} else {
|
||||
offset.x = svgX;
|
||||
offset.y = svgY;
|
||||
}
|
||||
}
|
||||
|
||||
_this.processing.buffer.push([svgClone, AmCharts.extend({}, offset)]);
|
||||
|
||||
// Put back from "cache"
|
||||
if (svgY && svgX) {
|
||||
offset = tmp;
|
||||
|
||||
// New offset for next one
|
||||
} else {
|
||||
offset.y += svgY ? 0 : parent.offsetHeight;
|
||||
}
|
||||
|
||||
if (_this.DEBUG == 10) {
|
||||
_this.log('BUFFERED', svgs[i], offset);
|
||||
} // DEBUG
|
||||
}
|
||||
if (_this.DEBUG == 10) {
|
||||
_this.log('END BUFFERING');
|
||||
} // DEBUG
|
||||
|
||||
// Apply background
|
||||
if (_this.DEBUG == 10) {
|
||||
_this.log('START DRAWING', cfg.render);
|
||||
} // DEBUG
|
||||
if (_this.DEBUG == 10) {
|
||||
_this.log('FILL BACKGROUND');
|
||||
} // DEBUG
|
||||
canvas.id = AmCharts.getUniqueId();
|
||||
canvas.width = _this.chart.divRealWidth;
|
||||
canvas.height = _this.chart.divRealHeight;
|
||||
|
||||
// External legend exception
|
||||
if ( _this.chart.legend && _this.chart.legend.position == "outside" ) {
|
||||
if ( ['left','right'].indexOf(_this.cfg.legendPosition) != -1 ) {
|
||||
canvas.width += _this.chart.legend.div.offsetWidth;
|
||||
|
||||
} else if ( typeof _this.cfg.legendPosition == 'object' ) {
|
||||
canvas.width += _this.cfg.legendPosition.width;
|
||||
canvas.height += _this.cfg.legendPosition.height;
|
||||
|
||||
} else {
|
||||
canvas.height += _this.chart.legend.div.offsetHeight;
|
||||
}
|
||||
}
|
||||
|
||||
// Stockchart exception
|
||||
var adapted = {
|
||||
width: false,
|
||||
height: false
|
||||
};
|
||||
if ( _this.chart.periodSelector ) {
|
||||
if ( ['left','right'].indexOf(_this.chart.periodSelector.position) != -1 ) {
|
||||
canvas.width -= _this.chart.periodSelector.div.offsetWidth + 16;
|
||||
adapted.width = true;
|
||||
} else {
|
||||
canvas.height -= _this.chart.periodSelector.div.offsetHeight;
|
||||
adapted.height = true;
|
||||
}
|
||||
}
|
||||
|
||||
if ( _this.chart.dataSetSelector ) {
|
||||
if ( ['left','right'].indexOf(_this.chart.dataSetSelector.position) != -1 ) {
|
||||
if ( !adapted.width ) {
|
||||
canvas.width -= _this.chart.dataSetSelector.div.offsetWidth + 16;
|
||||
}
|
||||
} else {
|
||||
canvas.height -= _this.chart.dataSetSelector.div.offsetHeight;
|
||||
}
|
||||
}
|
||||
|
||||
// Set given background; jpeg default
|
||||
if (cfg.backgroundColor || cfg.format == 'image/jpeg') {
|
||||
context.fillStyle = cfg.backgroundColor || '#FFFFFF';
|
||||
context.fillRect(0, 0, canvas.width, canvas.height);
|
||||
}
|
||||
|
||||
/* PRIVATE
|
||||
Recursive function to draw the images to the canvas;
|
||||
@param none;
|
||||
*/
|
||||
function drawItWhenItsLoaded() {
|
||||
var img, buffer, offset, source;
|
||||
|
||||
// DRAWING PROCESS DONE
|
||||
if (_this.processing.buffer.length == _this.processing.drawn || cfg.format == 'svg' ) {
|
||||
if (_this.DEBUG == 10) {
|
||||
_this.log('END DRAWING');
|
||||
} // DEBUG
|
||||
return callback();
|
||||
|
||||
// LOOPING LUI
|
||||
} else {
|
||||
if (_this.DEBUG == 10) {
|
||||
_this.log('DRAW', _this.processing.drawn + 1, 'OF', _this.processing.buffer.length);
|
||||
} // DEBUG
|
||||
|
||||
buffer = _this.processing.buffer[_this.processing.drawn];
|
||||
source = new XMLSerializer().serializeToString(buffer[0]); //source = 'data:image/svg+xml;base64,' + btoa();
|
||||
offset = buffer[1];
|
||||
|
||||
if (_this.DEBUG == 10) {
|
||||
_this.log('SOURCE', source);
|
||||
} // DEBUG
|
||||
|
||||
// NATIVE
|
||||
if (cfg.render == 'browser') {
|
||||
img = new Image();
|
||||
img.id = AmCharts.getUniqueId();
|
||||
source = 'data:image/svg+xml;base64,' + btoa(source);
|
||||
|
||||
//img.crossOrigin = "Anonymous";
|
||||
img.onload = function() {
|
||||
context.drawImage(this, buffer[1].x, buffer[1].y);
|
||||
_this.processing.drawn++;
|
||||
|
||||
if (_this.DEBUG == 10) {
|
||||
_this.log('ONLOAD', this);
|
||||
} // DEBUG
|
||||
drawItWhenItsLoaded();
|
||||
};
|
||||
img.onerror = function() {
|
||||
if (_this.DEBUG == 10) {
|
||||
_this.log('ONERROR', this);
|
||||
} // DEBUG
|
||||
context.drawImage(this, buffer[1].x, buffer[1].y);
|
||||
_this.processing.drawn++;
|
||||
drawItWhenItsLoaded();
|
||||
};
|
||||
img.src = source;
|
||||
|
||||
if (_this.DEBUG == 10) {
|
||||
_this.log('ADD', img);
|
||||
} // DEBUG
|
||||
if (img.complete || typeof(img.complete) == 'undefined' || img.complete === undefined) {
|
||||
if (_this.DEBUG == 10) {
|
||||
_this.log('FORCE ONLOAD', img);
|
||||
} // DEBUG
|
||||
img.src = "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///ywAAAAAAQABAAACAUwAOw==";
|
||||
img.src = source;
|
||||
}
|
||||
|
||||
// CANVG
|
||||
} else if (cfg.render == 'canvg') {
|
||||
canvg(canvas, source, {
|
||||
offsetX: offset.x,
|
||||
offsetY: offset.y,
|
||||
ignoreMouse: true,
|
||||
ignoreAnimation: true,
|
||||
ignoreDimensions: true,
|
||||
ignoreClear: true,
|
||||
renderCallback: function() {
|
||||
_this.processing.drawn++;
|
||||
drawItWhenItsLoaded();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
return drawItWhenItsLoaded();
|
||||
},
|
||||
|
||||
/*
|
||||
Generates the export menu to trigger the exportation
|
||||
@param none;
|
||||
*/
|
||||
generateButtons: function() {
|
||||
var _this = this,lvl = 0;
|
||||
|
||||
if(_this.div){
|
||||
div = _this.div;
|
||||
div.innerHTML = "";
|
||||
}
|
||||
else{
|
||||
div = document.createElement('div'),
|
||||
_this.div = div;
|
||||
}
|
||||
|
||||
// Push sublings
|
||||
function createList(items) {
|
||||
var ul = document.createElement('ul');
|
||||
|
||||
ul.setAttribute('style', 'list-style: none; margin: 0; padding: 0;');
|
||||
|
||||
// Walkthrough items
|
||||
for (var i = 0; i < items.length; i++) {
|
||||
var li = document.createElement('li'),
|
||||
img = document.createElement('img'),
|
||||
a = document.createElement('a'),
|
||||
item = items[i],
|
||||
children = null,
|
||||
itemStyle = AmCharts.extend(AmCharts.extend({}, _this.cfg.menuItemStyle), items[i]);
|
||||
|
||||
// MERGE CFG
|
||||
item = AmCharts.extend(AmCharts.extend({}, _this.cfg.menuItemOutput), item);
|
||||
|
||||
// ICON
|
||||
if (item['icon']) {
|
||||
img.alt = '';
|
||||
img.src = item['icon'];
|
||||
img.setAttribute('style', 'margin: 0 auto;border: none;outline: none');
|
||||
if (item['iconTitle']) {
|
||||
img.title = item['iconTitle'];
|
||||
}
|
||||
a.appendChild(img);
|
||||
}
|
||||
|
||||
// TITLE; STYLING
|
||||
a.href = '#';
|
||||
if (item['title']) {
|
||||
img.setAttribute('style', 'margin: 0px 5px;');
|
||||
a.innerHTML += item.title;
|
||||
}
|
||||
a.setAttribute('style', 'display: block;');
|
||||
AmCharts.extend(a.style, itemStyle);
|
||||
|
||||
// ONCLICK
|
||||
a.onclick = item.onclick.bind(a, _this, item);
|
||||
li.appendChild(a);
|
||||
|
||||
// APPEND SIBLINGS
|
||||
if (item.items) {
|
||||
children = createList(item.items);
|
||||
li.appendChild(children);
|
||||
|
||||
li.onmouseover = function() {
|
||||
children.style.display = 'block';
|
||||
};
|
||||
li.onmouseout = function() {
|
||||
children.style.display = 'none';
|
||||
};
|
||||
children.style.display = 'none';
|
||||
}
|
||||
|
||||
// Append to parent
|
||||
ul.appendChild(li);
|
||||
|
||||
// Apply hover
|
||||
a.onmouseover = function() {
|
||||
this.style.backgroundColor = itemStyle.rollOverBackgroundColor;
|
||||
this.style.color = itemStyle.rollOverColor;
|
||||
this.style.borderColor = itemStyle.rollOverBorderColor;
|
||||
};
|
||||
a.onmouseout = function() {
|
||||
this.style.backgroundColor = itemStyle.backgroundColor;
|
||||
this.style.color = itemStyle.color;
|
||||
this.style.borderColor = itemStyle.borderColor;
|
||||
};
|
||||
}
|
||||
lvl++;
|
||||
|
||||
if (_this.DEBUG == 10) {
|
||||
_this.log('MENU', ul);
|
||||
} // DEBUG
|
||||
|
||||
return ul;
|
||||
}
|
||||
|
||||
// Style wrapper; Push into chart div
|
||||
div.setAttribute('style', 'position: absolute;top:' + _this.cfg.menuTop + ';right:' + _this.cfg.menuRight + ';bottom:' + _this.cfg.menuBottom + ';left:' + _this.cfg.menuLeft + ';');
|
||||
div.setAttribute('class', 'amExportButton');
|
||||
div.appendChild(createList(_this.cfg.menuItems));
|
||||
_this.chart.containerDiv.appendChild(div);
|
||||
}
|
||||
});
|
||||
2842
Metronic/assets/global/plugins/amcharts/ammap/exporting/canvg.js
Normal file
2842
Metronic/assets/global/plugins/amcharts/ammap/exporting/canvg.js
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,233 @@
|
||||
/* FileSaver.js
|
||||
* A saveAs() FileSaver implementation.
|
||||
* 2013-10-21
|
||||
*
|
||||
* By Eli Grey, http://eligrey.com
|
||||
* License: X11/MIT
|
||||
* See LICENSE.md
|
||||
*/
|
||||
|
||||
/*global self */
|
||||
/*jslint bitwise: true, regexp: true, confusion: true, es5: true, vars: true, white: true,
|
||||
plusplus: true */
|
||||
|
||||
/*! @source http://purl.eligrey.com/github/FileSaver.js/blob/master/FileSaver.js */
|
||||
if(AmCharts.isModern){ /// added by AmCharts to avoid old IE problems if this file is included
|
||||
var saveAs = saveAs
|
||||
|| (typeof navigator !== 'undefined' && navigator.msSaveOrOpenBlob && navigator.msSaveOrOpenBlob.bind(navigator))
|
||||
|| (function(view) {
|
||||
"use strict";
|
||||
var
|
||||
doc = view.document
|
||||
// only get URL when necessary in case BlobBuilder.js hasn't overridden it yet
|
||||
, get_URL = function() {
|
||||
return view.URL || view.webkitURL || view;
|
||||
}
|
||||
, URL = view.URL || view.webkitURL || view
|
||||
, save_link = doc.createElementNS("http://www.w3.org/1999/xhtml", "a")
|
||||
, can_use_save_link = !view.externalHost && "download" in save_link
|
||||
, click = function(node) {
|
||||
var event = doc.createEvent("MouseEvents");
|
||||
event.initMouseEvent(
|
||||
"click", true, false, view, 0, 0, 0, 0, 0
|
||||
, false, false, false, false, 0, null
|
||||
);
|
||||
node.dispatchEvent(event);
|
||||
}
|
||||
, webkit_req_fs = view.webkitRequestFileSystem
|
||||
, req_fs = view.requestFileSystem || webkit_req_fs || view.mozRequestFileSystem
|
||||
, throw_outside = function (ex) {
|
||||
(view.setImmediate || view.setTimeout)(function() {
|
||||
throw ex;
|
||||
}, 0);
|
||||
}
|
||||
, force_saveable_type = "application/octet-stream"
|
||||
, fs_min_size = 0
|
||||
, deletion_queue = []
|
||||
, process_deletion_queue = function() {
|
||||
var i = deletion_queue.length;
|
||||
while (i--) {
|
||||
var file = deletion_queue[i];
|
||||
if (typeof file === "string") { // file is an object URL
|
||||
URL.revokeObjectURL(file);
|
||||
} else { // file is a File
|
||||
file.remove();
|
||||
}
|
||||
}
|
||||
deletion_queue.length = 0; // clear queue
|
||||
}
|
||||
, dispatch = function(filesaver, event_types, event) {
|
||||
event_types = [].concat(event_types);
|
||||
var i = event_types.length;
|
||||
while (i--) {
|
||||
var listener = filesaver["on" + event_types[i]];
|
||||
if (typeof listener === "function") {
|
||||
try {
|
||||
listener.call(filesaver, event || filesaver);
|
||||
} catch (ex) {
|
||||
throw_outside(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
, FileSaver = function(blob, name) {
|
||||
// First try a.download, then web filesystem, then object URLs
|
||||
var
|
||||
filesaver = this
|
||||
, type = blob.type
|
||||
, blob_changed = false
|
||||
, object_url
|
||||
, target_view
|
||||
, get_object_url = function() {
|
||||
var object_url = get_URL().createObjectURL(blob);
|
||||
deletion_queue.push(object_url);
|
||||
return object_url;
|
||||
}
|
||||
, dispatch_all = function() {
|
||||
dispatch(filesaver, "writestart progress write writeend".split(" "));
|
||||
}
|
||||
// on any filesys errors revert to saving with object URLs
|
||||
, fs_error = function() {
|
||||
// don't create more object URLs than needed
|
||||
if (blob_changed || !object_url) {
|
||||
object_url = get_object_url(blob);
|
||||
}
|
||||
if (target_view) {
|
||||
target_view.location.href = object_url;
|
||||
} else {
|
||||
window.open(object_url, "_blank");
|
||||
}
|
||||
filesaver.readyState = filesaver.DONE;
|
||||
dispatch_all();
|
||||
}
|
||||
, abortable = function(func) {
|
||||
return function() {
|
||||
if (filesaver.readyState !== filesaver.DONE) {
|
||||
return func.apply(this, arguments);
|
||||
}
|
||||
};
|
||||
}
|
||||
, create_if_not_found = {create: true, exclusive: false}
|
||||
, slice
|
||||
;
|
||||
filesaver.readyState = filesaver.INIT;
|
||||
if (!name) {
|
||||
name = "download";
|
||||
}
|
||||
if (can_use_save_link) {
|
||||
object_url = get_object_url(blob);
|
||||
// FF for Android has a nasty garbage collection mechanism
|
||||
// that turns all objects that are not pure javascript into 'deadObject'
|
||||
// this means `doc` and `save_link` are unusable and need to be recreated
|
||||
// `view` is usable though:
|
||||
doc = view.document;
|
||||
save_link = doc.createElementNS("http://www.w3.org/1999/xhtml", "a");
|
||||
save_link.href = object_url;
|
||||
save_link.download = name;
|
||||
var event = doc.createEvent("MouseEvents");
|
||||
event.initMouseEvent(
|
||||
"click", true, false, view, 0, 0, 0, 0, 0
|
||||
, false, false, false, false, 0, null
|
||||
);
|
||||
save_link.dispatchEvent(event);
|
||||
filesaver.readyState = filesaver.DONE;
|
||||
dispatch_all();
|
||||
return;
|
||||
}
|
||||
// Object and web filesystem URLs have a problem saving in Google Chrome when
|
||||
// viewed in a tab, so I force save with application/octet-stream
|
||||
// http://code.google.com/p/chromium/issues/detail?id=91158
|
||||
if (view.chrome && type && type !== force_saveable_type) {
|
||||
slice = blob.slice || blob.webkitSlice;
|
||||
blob = slice.call(blob, 0, blob.size, force_saveable_type);
|
||||
blob_changed = true;
|
||||
}
|
||||
// Since I can't be sure that the guessed media type will trigger a download
|
||||
// in WebKit, I append .download to the filename.
|
||||
// https://bugs.webkit.org/show_bug.cgi?id=65440
|
||||
if (webkit_req_fs && name !== "download") {
|
||||
name += ".download";
|
||||
}
|
||||
if (type === force_saveable_type || webkit_req_fs) {
|
||||
target_view = view;
|
||||
}
|
||||
if (!req_fs) {
|
||||
fs_error();
|
||||
return;
|
||||
}
|
||||
fs_min_size += blob.size;
|
||||
req_fs(view.TEMPORARY, fs_min_size, abortable(function(fs) {
|
||||
fs.root.getDirectory("saved", create_if_not_found, abortable(function(dir) {
|
||||
var save = function() {
|
||||
dir.getFile(name, create_if_not_found, abortable(function(file) {
|
||||
file.createWriter(abortable(function(writer) {
|
||||
writer.onwriteend = function(event) {
|
||||
target_view.location.href = file.toURL();
|
||||
deletion_queue.push(file);
|
||||
filesaver.readyState = filesaver.DONE;
|
||||
dispatch(filesaver, "writeend", event);
|
||||
};
|
||||
writer.onerror = function() {
|
||||
var error = writer.error;
|
||||
if (error.code !== error.ABORT_ERR) {
|
||||
fs_error();
|
||||
}
|
||||
};
|
||||
"writestart progress write abort".split(" ").forEach(function(event) {
|
||||
writer["on" + event] = filesaver["on" + event];
|
||||
});
|
||||
writer.write(blob);
|
||||
filesaver.abort = function() {
|
||||
writer.abort();
|
||||
filesaver.readyState = filesaver.DONE;
|
||||
};
|
||||
filesaver.readyState = filesaver.WRITING;
|
||||
}), fs_error);
|
||||
}), fs_error);
|
||||
};
|
||||
dir.getFile(name, {create: false}, abortable(function(file) {
|
||||
// delete file if it already exists
|
||||
file.remove();
|
||||
save();
|
||||
}), abortable(function(ex) {
|
||||
if (ex.code === ex.NOT_FOUND_ERR) {
|
||||
save();
|
||||
} else {
|
||||
fs_error();
|
||||
}
|
||||
}));
|
||||
}), fs_error);
|
||||
}), fs_error);
|
||||
}
|
||||
, FS_proto = FileSaver.prototype
|
||||
, saveAs = function(blob, name) {
|
||||
return new FileSaver(blob, name);
|
||||
}
|
||||
;
|
||||
FS_proto.abort = function() {
|
||||
var filesaver = this;
|
||||
filesaver.readyState = filesaver.DONE;
|
||||
dispatch(filesaver, "abort");
|
||||
};
|
||||
FS_proto.readyState = FS_proto.INIT = 0;
|
||||
FS_proto.WRITING = 1;
|
||||
FS_proto.DONE = 2;
|
||||
|
||||
FS_proto.error =
|
||||
FS_proto.onwritestart =
|
||||
FS_proto.onprogress =
|
||||
FS_proto.onwrite =
|
||||
FS_proto.onabort =
|
||||
FS_proto.onerror =
|
||||
FS_proto.onwriteend =
|
||||
null;
|
||||
|
||||
view.addEventListener("unload", process_deletion_queue, false);
|
||||
return saveAs;
|
||||
}(this.self || this.window || this.content));
|
||||
// `self` is undefined in Firefox for Android content script context
|
||||
// while `this` is nsIContentFrameMessageManager
|
||||
// with an attribute `content` that corresponds to the window
|
||||
|
||||
if (typeof module !== 'undefined') module.exports = saveAs;
|
||||
}/// added by AmCharts to avoid old IE problems if this file is included
|
||||
1943
Metronic/assets/global/plugins/amcharts/ammap/exporting/jspdf.js
Normal file
1943
Metronic/assets/global/plugins/amcharts/ammap/exporting/jspdf.js
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,230 @@
|
||||
/** @preserve
|
||||
jsPDF addImage plugin (JPEG only at this time)
|
||||
Copyright (c) 2012 https://github.com/siefkenj/
|
||||
*/
|
||||
|
||||
/**
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
;(function(jsPDFAPI) {
|
||||
'use strict'
|
||||
|
||||
var namespace = 'addImage_'
|
||||
|
||||
// takes a string imgData containing the raw bytes of
|
||||
// a jpeg image and returns [width, height]
|
||||
// Algorithm from: http://www.64lines.com/jpeg-width-height
|
||||
var getJpegSize = function(imgData) {
|
||||
'use strict'
|
||||
var width, height;
|
||||
// Verify we have a valid jpeg header 0xff,0xd8,0xff,0xe0,?,?,'J','F','I','F',0x00
|
||||
if (!imgData.charCodeAt(0) === 0xff ||
|
||||
!imgData.charCodeAt(1) === 0xd8 ||
|
||||
!imgData.charCodeAt(2) === 0xff ||
|
||||
!imgData.charCodeAt(3) === 0xe0 ||
|
||||
!imgData.charCodeAt(6) === 'J'.charCodeAt(0) ||
|
||||
!imgData.charCodeAt(7) === 'F'.charCodeAt(0) ||
|
||||
!imgData.charCodeAt(8) === 'I'.charCodeAt(0) ||
|
||||
!imgData.charCodeAt(9) === 'F'.charCodeAt(0) ||
|
||||
!imgData.charCodeAt(10) === 0x00) {
|
||||
throw new Error('getJpegSize requires a binary jpeg file')
|
||||
}
|
||||
var blockLength = imgData.charCodeAt(4)*256 + imgData.charCodeAt(5);
|
||||
var i = 4, len = imgData.length;
|
||||
while ( i < len ) {
|
||||
i += blockLength;
|
||||
if (imgData.charCodeAt(i) !== 0xff) {
|
||||
throw new Error('getJpegSize could not find the size of the image');
|
||||
}
|
||||
if (imgData.charCodeAt(i+1) === 0xc0 || //(SOF) Huffman - Baseline DCT
|
||||
imgData.charCodeAt(i+1) === 0xc1 || //(SOF) Huffman - Extended sequential DCT
|
||||
imgData.charCodeAt(i+1) === 0xc2 || // Progressive DCT (SOF2)
|
||||
imgData.charCodeAt(i+1) === 0xc3 || // Spatial (sequential) lossless (SOF3)
|
||||
imgData.charCodeAt(i+1) === 0xc4 || // Differential sequential DCT (SOF5)
|
||||
imgData.charCodeAt(i+1) === 0xc5 || // Differential progressive DCT (SOF6)
|
||||
imgData.charCodeAt(i+1) === 0xc6 || // Differential spatial (SOF7)
|
||||
imgData.charCodeAt(i+1) === 0xc7) {
|
||||
height = imgData.charCodeAt(i+5)*256 + imgData.charCodeAt(i+6);
|
||||
width = imgData.charCodeAt(i+7)*256 + imgData.charCodeAt(i+8);
|
||||
return [width, height];
|
||||
} else {
|
||||
i += 2;
|
||||
blockLength = imgData.charCodeAt(i)*256 + imgData.charCodeAt(i+1)
|
||||
}
|
||||
}
|
||||
}
|
||||
// Image functionality ported from pdf.js
|
||||
, putImage = function(img) {
|
||||
var objectNumber = this.internal.newObject()
|
||||
, out = this.internal.write
|
||||
, putStream = this.internal.putStream
|
||||
|
||||
img['n'] = objectNumber
|
||||
|
||||
out('<</Type /XObject')
|
||||
out('/Subtype /Image')
|
||||
out('/Width ' + img['w'])
|
||||
out('/Height ' + img['h'])
|
||||
if (img['cs'] === 'Indexed') {
|
||||
out('/ColorSpace [/Indexed /DeviceRGB '
|
||||
+ (img['pal'].length / 3 - 1) + ' ' + (objectNumber + 1)
|
||||
+ ' 0 R]');
|
||||
} else {
|
||||
out('/ColorSpace /' + img['cs']);
|
||||
if (img['cs'] === 'DeviceCMYK') {
|
||||
out('/Decode [1 0 1 0 1 0 1 0]');
|
||||
}
|
||||
}
|
||||
out('/BitsPerComponent ' + img['bpc']);
|
||||
if ('f' in img) {
|
||||
out('/Filter /' + img['f']);
|
||||
}
|
||||
if ('dp' in img) {
|
||||
out('/DecodeParms <<' + img['dp'] + '>>');
|
||||
}
|
||||
if ('trns' in img && img['trns'].constructor == Array) {
|
||||
var trns = '';
|
||||
for ( var i = 0; i < img['trns'].length; i++) {
|
||||
trns += (img[trns][i] + ' ' + img['trns'][i] + ' ');
|
||||
out('/Mask [' + trns + ']');
|
||||
}
|
||||
}
|
||||
if ('smask' in img) {
|
||||
out('/SMask ' + (objectNumber + 1) + ' 0 R');
|
||||
}
|
||||
out('/Length ' + img['data'].length + '>>');
|
||||
|
||||
putStream(img['data']);
|
||||
|
||||
out('endobj');
|
||||
}
|
||||
, putResourcesCallback = function() {
|
||||
var images = this.internal.collections[namespace + 'images']
|
||||
for ( var i in images ) {
|
||||
putImage.call(this, images[i])
|
||||
}
|
||||
}
|
||||
, putXObjectsDictCallback = function(){
|
||||
var images = this.internal.collections[namespace + 'images']
|
||||
, out = this.internal.write
|
||||
, image
|
||||
for (var i in images) {
|
||||
image = images[i]
|
||||
out(
|
||||
'/I' + image['i']
|
||||
, image['n']
|
||||
, '0'
|
||||
, 'R'
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
jsPDFAPI.addImage = function(imageData, format, x, y, w, h) {
|
||||
'use strict'
|
||||
if (typeof imageData === 'object' && imageData.nodeType === 1) {
|
||||
var canvas = document.createElement('canvas');
|
||||
canvas.width = imageData.clientWidth;
|
||||
canvas.height = imageData.clientHeight;
|
||||
|
||||
var ctx = canvas.getContext('2d');
|
||||
if (!ctx) {
|
||||
throw ('addImage requires canvas to be supported by browser.');
|
||||
}
|
||||
ctx.drawImage(imageData, 0, 0, canvas.width, canvas.height);
|
||||
imageData = canvas.toDataURL('image/jpeg');
|
||||
format = "JPEG";
|
||||
}
|
||||
if (format.toUpperCase() !== 'JPEG') {
|
||||
throw new Error('addImage currently only supports format \'JPEG\', not \''+format+'\'');
|
||||
}
|
||||
|
||||
var imageIndex
|
||||
, images = this.internal.collections[namespace + 'images']
|
||||
, coord = this.internal.getCoordinateString
|
||||
, vcoord = this.internal.getVerticalCoordinateString;
|
||||
|
||||
// Detect if the imageData is raw binary or Data URL
|
||||
if (imageData.substring(0, 23) === 'data:image/jpeg;base64,') {
|
||||
imageData = atob(imageData.replace('data:image/jpeg;base64,', ''));
|
||||
}
|
||||
|
||||
if (images){
|
||||
// this is NOT the first time this method is ran on this instance of jsPDF object.
|
||||
imageIndex = Object.keys ?
|
||||
Object.keys(images).length :
|
||||
(function(o){
|
||||
var i = 0
|
||||
for (var e in o){if(o.hasOwnProperty(e)){ i++ }}
|
||||
return i
|
||||
})(images)
|
||||
} else {
|
||||
// this is the first time this method is ran on this instance of jsPDF object.
|
||||
imageIndex = 0
|
||||
this.internal.collections[namespace + 'images'] = images = {}
|
||||
this.internal.events.subscribe('putResources', putResourcesCallback)
|
||||
this.internal.events.subscribe('putXobjectDict', putXObjectsDictCallback)
|
||||
}
|
||||
|
||||
var dims = getJpegSize(imageData);
|
||||
var info = {
|
||||
w : dims[0],
|
||||
h : dims[1],
|
||||
cs : 'DeviceRGB',
|
||||
bpc : 8,
|
||||
f : 'DCTDecode',
|
||||
i : imageIndex,
|
||||
data : imageData
|
||||
// n: objectNumber will be added by putImage code
|
||||
|
||||
};
|
||||
images[imageIndex] = info
|
||||
if (!w && !h) {
|
||||
w = -96;
|
||||
h = -96;
|
||||
}
|
||||
if (w < 0) {
|
||||
w = (-1) * info['w'] * 72 / w / this.internal.scaleFactor;
|
||||
}
|
||||
if (h < 0) {
|
||||
h = (-1) * info['h'] * 72 / h / this.internal.scaleFactor;
|
||||
}
|
||||
if (w === 0) {
|
||||
w = h * info['w'] / info['h'];
|
||||
}
|
||||
if (h === 0) {
|
||||
h = w * info['h'] / info['w'];
|
||||
}
|
||||
|
||||
this.internal.write(
|
||||
'q'
|
||||
, coord(w)
|
||||
, '0 0'
|
||||
, coord(h) // TODO: check if this should be shifted by vcoord
|
||||
, coord(x)
|
||||
, vcoord(y + h)
|
||||
, 'cm /I'+info['i']
|
||||
, 'Do Q'
|
||||
)
|
||||
|
||||
return this
|
||||
}
|
||||
})(jsPDF.API)
|
||||
@@ -0,0 +1,288 @@
|
||||
/**
|
||||
* A class to parse color values
|
||||
* @author Stoyan Stefanov <sstoo@gmail.com>
|
||||
* @link http://www.phpied.com/rgb-color-parser-in-javascript/
|
||||
* @license Use it if you like it
|
||||
*/
|
||||
function RGBColor(color_string)
|
||||
{
|
||||
this.ok = false;
|
||||
|
||||
// strip any leading #
|
||||
if (color_string.charAt(0) == '#') { // remove # if any
|
||||
color_string = color_string.substr(1,6);
|
||||
}
|
||||
|
||||
color_string = color_string.replace(/ /g,'');
|
||||
color_string = color_string.toLowerCase();
|
||||
|
||||
// before getting into regexps, try simple matches
|
||||
// and overwrite the input
|
||||
var simple_colors = {
|
||||
aliceblue: 'f0f8ff',
|
||||
antiquewhite: 'faebd7',
|
||||
aqua: '00ffff',
|
||||
aquamarine: '7fffd4',
|
||||
azure: 'f0ffff',
|
||||
beige: 'f5f5dc',
|
||||
bisque: 'ffe4c4',
|
||||
black: '000000',
|
||||
blanchedalmond: 'ffebcd',
|
||||
blue: '0000ff',
|
||||
blueviolet: '8a2be2',
|
||||
brown: 'a52a2a',
|
||||
burlywood: 'deb887',
|
||||
cadetblue: '5f9ea0',
|
||||
chartreuse: '7fff00',
|
||||
chocolate: 'd2691e',
|
||||
coral: 'ff7f50',
|
||||
cornflowerblue: '6495ed',
|
||||
cornsilk: 'fff8dc',
|
||||
crimson: 'dc143c',
|
||||
cyan: '00ffff',
|
||||
darkblue: '00008b',
|
||||
darkcyan: '008b8b',
|
||||
darkgoldenrod: 'b8860b',
|
||||
darkgray: 'a9a9a9',
|
||||
darkgreen: '006400',
|
||||
darkkhaki: 'bdb76b',
|
||||
darkmagenta: '8b008b',
|
||||
darkolivegreen: '556b2f',
|
||||
darkorange: 'ff8c00',
|
||||
darkorchid: '9932cc',
|
||||
darkred: '8b0000',
|
||||
darksalmon: 'e9967a',
|
||||
darkseagreen: '8fbc8f',
|
||||
darkslateblue: '483d8b',
|
||||
darkslategray: '2f4f4f',
|
||||
darkturquoise: '00ced1',
|
||||
darkviolet: '9400d3',
|
||||
deeppink: 'ff1493',
|
||||
deepskyblue: '00bfff',
|
||||
dimgray: '696969',
|
||||
dodgerblue: '1e90ff',
|
||||
feldspar: 'd19275',
|
||||
firebrick: 'b22222',
|
||||
floralwhite: 'fffaf0',
|
||||
forestgreen: '228b22',
|
||||
fuchsia: 'ff00ff',
|
||||
gainsboro: 'dcdcdc',
|
||||
ghostwhite: 'f8f8ff',
|
||||
gold: 'ffd700',
|
||||
goldenrod: 'daa520',
|
||||
gray: '808080',
|
||||
green: '008000',
|
||||
greenyellow: 'adff2f',
|
||||
honeydew: 'f0fff0',
|
||||
hotpink: 'ff69b4',
|
||||
indianred : 'cd5c5c',
|
||||
indigo : '4b0082',
|
||||
ivory: 'fffff0',
|
||||
khaki: 'f0e68c',
|
||||
lavender: 'e6e6fa',
|
||||
lavenderblush: 'fff0f5',
|
||||
lawngreen: '7cfc00',
|
||||
lemonchiffon: 'fffacd',
|
||||
lightblue: 'add8e6',
|
||||
lightcoral: 'f08080',
|
||||
lightcyan: 'e0ffff',
|
||||
lightgoldenrodyellow: 'fafad2',
|
||||
lightgrey: 'd3d3d3',
|
||||
lightgreen: '90ee90',
|
||||
lightpink: 'ffb6c1',
|
||||
lightsalmon: 'ffa07a',
|
||||
lightseagreen: '20b2aa',
|
||||
lightskyblue: '87cefa',
|
||||
lightslateblue: '8470ff',
|
||||
lightslategray: '778899',
|
||||
lightsteelblue: 'b0c4de',
|
||||
lightyellow: 'ffffe0',
|
||||
lime: '00ff00',
|
||||
limegreen: '32cd32',
|
||||
linen: 'faf0e6',
|
||||
magenta: 'ff00ff',
|
||||
maroon: '800000',
|
||||
mediumaquamarine: '66cdaa',
|
||||
mediumblue: '0000cd',
|
||||
mediumorchid: 'ba55d3',
|
||||
mediumpurple: '9370d8',
|
||||
mediumseagreen: '3cb371',
|
||||
mediumslateblue: '7b68ee',
|
||||
mediumspringgreen: '00fa9a',
|
||||
mediumturquoise: '48d1cc',
|
||||
mediumvioletred: 'c71585',
|
||||
midnightblue: '191970',
|
||||
mintcream: 'f5fffa',
|
||||
mistyrose: 'ffe4e1',
|
||||
moccasin: 'ffe4b5',
|
||||
navajowhite: 'ffdead',
|
||||
navy: '000080',
|
||||
oldlace: 'fdf5e6',
|
||||
olive: '808000',
|
||||
olivedrab: '6b8e23',
|
||||
orange: 'ffa500',
|
||||
orangered: 'ff4500',
|
||||
orchid: 'da70d6',
|
||||
palegoldenrod: 'eee8aa',
|
||||
palegreen: '98fb98',
|
||||
paleturquoise: 'afeeee',
|
||||
palevioletred: 'd87093',
|
||||
papayawhip: 'ffefd5',
|
||||
peachpuff: 'ffdab9',
|
||||
peru: 'cd853f',
|
||||
pink: 'ffc0cb',
|
||||
plum: 'dda0dd',
|
||||
powderblue: 'b0e0e6',
|
||||
purple: '800080',
|
||||
red: 'ff0000',
|
||||
rosybrown: 'bc8f8f',
|
||||
royalblue: '4169e1',
|
||||
saddlebrown: '8b4513',
|
||||
salmon: 'fa8072',
|
||||
sandybrown: 'f4a460',
|
||||
seagreen: '2e8b57',
|
||||
seashell: 'fff5ee',
|
||||
sienna: 'a0522d',
|
||||
silver: 'c0c0c0',
|
||||
skyblue: '87ceeb',
|
||||
slateblue: '6a5acd',
|
||||
slategray: '708090',
|
||||
snow: 'fffafa',
|
||||
springgreen: '00ff7f',
|
||||
steelblue: '4682b4',
|
||||
tan: 'd2b48c',
|
||||
teal: '008080',
|
||||
thistle: 'd8bfd8',
|
||||
tomato: 'ff6347',
|
||||
turquoise: '40e0d0',
|
||||
violet: 'ee82ee',
|
||||
violetred: 'd02090',
|
||||
wheat: 'f5deb3',
|
||||
white: 'ffffff',
|
||||
whitesmoke: 'f5f5f5',
|
||||
yellow: 'ffff00',
|
||||
yellowgreen: '9acd32'
|
||||
};
|
||||
for (var key in simple_colors) {
|
||||
if (color_string == key) {
|
||||
color_string = simple_colors[key];
|
||||
}
|
||||
}
|
||||
// emd of simple type-in colors
|
||||
|
||||
// array of color definition objects
|
||||
var color_defs = [
|
||||
{
|
||||
re: /^rgb\((\d{1,3}),\s*(\d{1,3}),\s*(\d{1,3})\)$/,
|
||||
example: ['rgb(123, 234, 45)', 'rgb(255,234,245)'],
|
||||
process: function (bits){
|
||||
return [
|
||||
parseInt(bits[1]),
|
||||
parseInt(bits[2]),
|
||||
parseInt(bits[3])
|
||||
];
|
||||
}
|
||||
},
|
||||
{
|
||||
re: /^(\w{2})(\w{2})(\w{2})$/,
|
||||
example: ['#00ff00', '336699'],
|
||||
process: function (bits){
|
||||
return [
|
||||
parseInt(bits[1], 16),
|
||||
parseInt(bits[2], 16),
|
||||
parseInt(bits[3], 16)
|
||||
];
|
||||
}
|
||||
},
|
||||
{
|
||||
re: /^(\w{1})(\w{1})(\w{1})$/,
|
||||
example: ['#fb0', 'f0f'],
|
||||
process: function (bits){
|
||||
return [
|
||||
parseInt(bits[1] + bits[1], 16),
|
||||
parseInt(bits[2] + bits[2], 16),
|
||||
parseInt(bits[3] + bits[3], 16)
|
||||
];
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
// search through the definitions to find a match
|
||||
for (var i = 0; i < color_defs.length; i++) {
|
||||
var re = color_defs[i].re;
|
||||
var processor = color_defs[i].process;
|
||||
var bits = re.exec(color_string);
|
||||
if (bits) {
|
||||
channels = processor(bits);
|
||||
this.r = channels[0];
|
||||
this.g = channels[1];
|
||||
this.b = channels[2];
|
||||
this.ok = true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// validate/cleanup values
|
||||
this.r = (this.r < 0 || isNaN(this.r)) ? 0 : ((this.r > 255) ? 255 : this.r);
|
||||
this.g = (this.g < 0 || isNaN(this.g)) ? 0 : ((this.g > 255) ? 255 : this.g);
|
||||
this.b = (this.b < 0 || isNaN(this.b)) ? 0 : ((this.b > 255) ? 255 : this.b);
|
||||
|
||||
// some getters
|
||||
this.toRGB = function () {
|
||||
return 'rgb(' + this.r + ', ' + this.g + ', ' + this.b + ')';
|
||||
}
|
||||
this.toHex = function () {
|
||||
var r = this.r.toString(16);
|
||||
var g = this.g.toString(16);
|
||||
var b = this.b.toString(16);
|
||||
if (r.length == 1) r = '0' + r;
|
||||
if (g.length == 1) g = '0' + g;
|
||||
if (b.length == 1) b = '0' + b;
|
||||
return '#' + r + g + b;
|
||||
}
|
||||
|
||||
// help
|
||||
this.getHelpXML = function () {
|
||||
|
||||
var examples = new Array();
|
||||
// add regexps
|
||||
for (var i = 0; i < color_defs.length; i++) {
|
||||
var example = color_defs[i].example;
|
||||
for (var j = 0; j < example.length; j++) {
|
||||
examples[examples.length] = example[j];
|
||||
}
|
||||
}
|
||||
// add type-in colors
|
||||
for (var sc in simple_colors) {
|
||||
examples[examples.length] = sc;
|
||||
}
|
||||
|
||||
var xml = document.createElement('ul');
|
||||
xml.setAttribute('id', 'rgbcolor-examples');
|
||||
for (var i = 0; i < examples.length; i++) {
|
||||
try {
|
||||
var list_item = document.createElement('li');
|
||||
var list_color = new RGBColor(examples[i]);
|
||||
var example_div = document.createElement('div');
|
||||
example_div.style.cssText =
|
||||
'margin: 3px; '
|
||||
+ 'border: 1px solid black; '
|
||||
+ 'background:' + list_color.toHex() + '; '
|
||||
+ 'color:' + list_color.toHex()
|
||||
;
|
||||
example_div.appendChild(document.createTextNode('test'));
|
||||
var list_item_value = document.createTextNode(
|
||||
' ' + examples[i] + ' -> ' + list_color.toRGB() + ' -> ' + list_color.toHex()
|
||||
);
|
||||
list_item.appendChild(example_div);
|
||||
list_item.appendChild(list_item_value);
|
||||
xml.appendChild(list_item);
|
||||
|
||||
} catch(e){}
|
||||
}
|
||||
return xml;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user