/*
html2canvas 0.4.1 <http://html2canvas.hertzen.com>
Copyright (c) 2013 Niklas von Hertzen
Released under MIT License
*/
(function(window, document, undefined){
//"use strict";
var _html2canvas = {},
previousElement,
computedCSS,
html2canvas;
_html2canvas.Util = {};
_html2canvas.Util.log = function(a) {
if (_html2canvas.logging && window.console && window.console.log) {
window.console.log(a);
}
};
_html2canvas.Util.trimText = (function(isNative){
return function(input) {
return isNative ? isNative.apply(input) : ((input || '') + '').replace( /^\s+|\s+$/g , '' );
};
})(String.prototype.trim);
_html2canvas.Util.asFloat = function(v) {
return parseFloat(v);
};
(function() {
// TODO: support all possible length values
var TEXT_SHADOW_PROPERTY = /((rgba|rgb)\([^\)]+\)(\s-?\d+px){0,})/g;
var TEXT_SHADOW_VALUES = /(-?\d+px)|(#.+)|(rgb\(.+\))|(rgba\(.+\))/g;
_html2canvas.Util.parseTextShadows = function (value) {
if (!value || value === 'none') {
return [];
}
// find multiple shadow declarations
var shadows = value.match(TEXT_SHADOW_PROPERTY),
results = [];
for (var i = 0; shadows && (i < shadows.length); i++) {
var s = shadows[i].match(TEXT_SHADOW_VALUES);
results.push({
color: s[0],
offsetX: s[1] ? s[1].replace('px', '') : 0,
offsetY: s[2] ? s[2].replace('px', '') : 0,
blur: s[3] ? s[3].replace('px', '') : 0
});
}
return results;
};
})();
_html2canvas.Util.parseBackgroundImage = function (value) {
var whitespace = ' \r\n\t',
method, definition, prefix, prefix_i, block, results = [],
c, mode = 0, numParen = 0, quote, args;
var appendResult = function(){
if(method) {
if(definition.substr( 0, 1 ) === '"') {
definition = definition.substr( 1, definition.length - 2 );
}
if(definition) {
args.push(definition);
}
if(method.substr( 0, 1 ) === '-' &&
(prefix_i = method.indexOf( '-', 1 ) + 1) > 0) {
prefix = method.substr( 0, prefix_i);
method = method.substr( prefix_i );
}
results.push({
prefix: prefix,
method: method.toLowerCase(),
value: block,
args: args
});
}
args = []; //for some odd reason, setting .length = 0 didn't work in safari
method =
prefix =
definition =
block = '';
};
appendResult();
for(var i = 0, ii = value.length; i<ii; i++) {
c = value[i];
if(mode === 0 && whitespace.indexOf( c ) > -1){
continue;
}
switch(c) {
case '"':
if(!quote) {
quote = c;
}
else if(quote === c) {
quote = null;
}
break;
case '(':
if(quote) { break; }
else if(mode === 0) {
mode = 1;
block += c;
continue;
} else {
numParen++;
}
break;
case ')':
if(quote) { break; }
else if(mode === 1) {
if(numParen === 0) {
mode = 0;
block += c;
appendResult();
continue;
} else {
numParen--;
}
}
break;
case ',':
if(quote) { break; }
else if(mode === 0) {
appendResult();
continue;
}
else if (mode === 1) {
if(numParen === 0 && !method.match(/^url$/i)) {
args.push(definition);
definition = '';
block += c;
continue;
}
}
break;
}
block += c;
if(mode === 0) { method += c; }
else { definition += c; }
}
appendResult();
return results;
};
_html2canvas.Util.Bounds = function (element) {
var clientRect, bounds = {};
if (element.getBoundingClientRect){
clientRect = element.getBoundingClientRect();
// TODO add scroll position to bounds, so no scrolling of window necessary
bounds.top = clientRect.top;
bounds.bottom = clientRect.bottom || (clientRect.top + clientRect.height);
bounds.left = clientRect.left;
bounds.width = element.offsetWidth;
bounds.height = element.offsetHeight;
}
return bounds;
};
// TODO ideally, we'd want everything to go through this function instead of Util.Bounds,
// but would require further work to calculate the correct positions for elements with offsetParents
_html2canvas.Util.OffsetBounds = function (element) {
var parent = element.offsetParent ? _html2canvas.Util.OffsetBounds(element.offsetParent) : {top: 0, left: 0};
return {
top: element.offsetTop + parent.top,
bottom: element.offsetTop + element.offsetHeight + parent.top,
left: element.offsetLeft + parent.left,
width: element.offsetWidth,
height: element.offsetHeight
};
};
function toPX(element, attribute, value ) {
var rsLeft = element.runtimeStyle && element.runtimeStyle[attribute],
left,
style = element.style;
// Check if we are not dealing with pixels, (Opera has issues with this)
// Ported from jQuery css.js
// From the awesome hack by Dean Edwards
// http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291
// If we're not dealing with a regular pixel number
// but a number that has a weird ending, we need to convert it to pixels
if ( !/^-?[0-9]+\.?[0-9]*(?:px)?$/i.test( value ) && /^-?\d/.test(value) ) {
// Remember the original values
left = style.left;
// Put in the new values to get a computed value out
if (rsLeft) {
element.runtimeStyle.left = element.currentStyle.left;
}
style.left = attribute === "fontSize" ? "1em" : (value || 0);
value = style.pixelLeft + "px";
// Revert the changed values
style.left = left;
if (rsLeft) {
element.runtimeStyle.left = rsLeft;
}
}
if (!/^(thin|medium|thick)$/i.test(value)) {
return Math.round(parseFloat(value)) + "px";
}
return value;
}
function asInt(val) {
return parseInt(val, 10);
}
function isPercentage(value) {
return value.toString().indexOf("%") !== -1;
}
function parseBackgroundSizePosition(value, element, attribute, index) {
value = (value || '').split(',');
value = value[index || 0] || value[0] || 'auto';
value = _html2canvas.Util.trimText(value).split(' ');
if(attribute === 'backgroundSize' && (value[0] && value[0].match(/^(cover|contain|auto)$/))) {
return value;
} else {
value[0] = (value[0].indexOf( "%" ) === -1) ? toPX(element, attribute + "X", value[0]) : value[0];
if(value[1] === undefined) {
if(attribute === 'backgroundSize') {
value[1] = 'auto';
return value;
} else {
// IE 9 doesn't return double digit always
value[1] = value[0];
}
}
value[1] = (value[1].indexOf("%") === -1) ? toPX(element, attribute + "Y", value[1]) : value[1];
}
return value;
}
_html2canvas.Util.getCSS = function (element, attribute, index) {
if (previousElement !== element) {
computedCSS = document.defaultView.getComputedStyle(element, null);
}
var value = computedCSS[attribute];
if (/^background(Size|Position)$/.test(attribute)) {